From dc9dc13558e7c1359d1fe2010455ca4f6c880a96 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Fri, 23 Aug 2019 03:55:42 -0700 Subject: [PATCH] New upstream version 1.37.0+dfsg1 --- Cargo.lock | 986 +- README.md | 11 +- RELEASES.md | 126 +- config.toml.example | 33 +- git-commit-hash | 2 +- src/bootstrap/bin/rustc.rs | 37 +- src/bootstrap/builder.rs | 738 +- src/bootstrap/builder/tests.rs | 658 + src/bootstrap/cc_detect.rs | 44 +- src/bootstrap/channel.rs | 2 +- src/bootstrap/check.rs | 37 +- src/bootstrap/compile.rs | 95 +- src/bootstrap/config.rs | 82 +- src/bootstrap/configure.py | 10 +- src/bootstrap/dist.rs | 160 +- src/bootstrap/doc.rs | 112 +- src/bootstrap/flags.rs | 51 + src/bootstrap/install.rs | 80 +- src/bootstrap/job.rs | 9 +- src/bootstrap/lib.rs | 24 +- src/bootstrap/metadata.rs | 6 - src/bootstrap/mk/Makefile.in | 4 +- src/bootstrap/native.rs | 18 +- src/bootstrap/test.rs | 56 +- src/bootstrap/tool.rs | 65 +- src/bootstrap/util.rs | 22 +- src/build_helper/lib.rs | 6 +- src/ci/awscli-requirements.txt | 13 + src/ci/azure-pipelines/auto.yml | 350 + src/ci/azure-pipelines/master.yml | 25 + src/ci/azure-pipelines/pr.yml | 33 + .../azure-pipelines/steps/install-clang.yml | 40 + .../azure-pipelines/steps/install-sccache.yml | 21 + .../steps/install-windows-build-deps.yml | 94 + src/ci/azure-pipelines/steps/run.yml | 209 + src/ci/azure-pipelines/try.yml | 78 + src/ci/cpu-usage-over-time.py | 160 + src/ci/docker/armhf-gnu/Dockerfile | 2 +- src/ci/docker/asmjs/Dockerfile | 8 + src/ci/docker/dist-various-1/Dockerfile | 1 - .../dist-various-1/install-mips-musl.sh | 2 +- .../dist-various-1/install-mipsel-musl.sh | 2 +- src/ci/docker/dist-various-2/Dockerfile | 2 +- .../dist-various-2/build-wasi-toolchain.sh | 2 +- .../docker/dist-x86_64-linux/build-openssl.sh | 2 +- .../build-netbsd-toolchain.sh | 2 +- src/ci/docker/i686-gnu-nopt/Dockerfile | 2 +- src/ci/docker/run.sh | 21 +- src/ci/docker/scripts/emscripten.sh | 2 +- src/ci/docker/scripts/freebsd-toolchain.sh | 2 +- src/ci/docker/scripts/musl-toolchain.sh | 4 +- src/ci/docker/scripts/musl.sh | 2 +- src/ci/docker/scripts/sccache.sh | 2 +- src/ci/docker/test-various/Dockerfile | 4 - src/ci/docker/x86_64-gnu-distcheck/Dockerfile | 7 + .../x86_64-gnu-full-bootstrap/Dockerfile | 6 + src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile | 8 +- src/ci/docker/x86_64-gnu-nopt/Dockerfile | 2 +- src/ci/docker/x86_64-gnu-tools/checktools.sh | 13 +- src/ci/docker/x86_64-gnu-tools/repo.sh | 2 +- src/ci/init_repo.sh | 4 + src/ci/run.sh | 13 +- src/ci/shared.sh | 18 + src/doc/book/CONTRIBUTING.md | 2 +- src/doc/book/README.md | 4 +- src/doc/book/ci/dictionary.txt | 1 + src/doc/book/nostarch/appendices-d-and-e.md | 236 - .../book/nostarch/appendix-a-new-section.md | 57 - .../chapter11-using-result-in-tests.md | 37 - .../chapter12-error-message-updates.md | 12 - .../book/nostarch/chapter15-code-updates.md | 11 - .../chapter15-error-message-updates.md | 12 - ...-destructuring-nested-structs-and-enums.md | 54 - .../chapter19-new-function-pointer-text.md | 31 - src/doc/book/nostarch/chapter19.md | 579 - src/doc/book/src/appendix-02-operators.md | 12 +- .../book/src/appendix-03-derivable-traits.md | 12 +- .../appendix-04-useful-development-tools.md | 10 +- src/doc/book/src/appendix-05-editions.md | 1 + src/doc/book/src/appendix-06-translation.md | 1 + src/doc/book/src/ch01-03-hello-cargo.md | 8 +- .../src/ch02-00-guessing-game-tutorial.md | 10 +- src/doc/book/src/ch03-02-data-types.md | 9 +- src/doc/book/src/ch03-05-control-flow.md | 5 +- .../src/ch04-02-references-and-borrowing.md | 4 +- ...ojects-with-packages-crates-and-modules.md | 27 +- .../book/src/ch07-01-packages-and-crates.md | 14 +- ...ng-modules-to-control-scope-and-privacy.md | 46 +- ...referring-to-an-item-in-the-module-tree.md | 39 +- ...g-paths-into-scope-with-the-use-keyword.md | 20 +- src/doc/book/src/ch08-02-strings.md | 2 +- src/doc/book/src/ch08-03-hash-maps.md | 7 +- ...ch09-01-unrecoverable-errors-with-panic.md | 6 +- src/doc/book/src/ch10-02-traits.md | 15 +- src/doc/book/src/ch10-03-lifetime-syntax.md | 19 +- src/doc/book/src/ch11-01-writing-tests.md | 16 +- ...h12-01-accepting-command-line-arguments.md | 2 +- ...improving-error-handling-and-modularity.md | 17 +- src/doc/book/src/ch14-00-more-about-cargo.md | 4 +- .../src/ch14-02-publishing-to-crates-io.md | 18 +- src/doc/book/src/ch14-03-cargo-workspaces.md | 10 +- .../book/src/ch14-04-installing-binaries.md | 2 +- src/doc/book/src/ch14-05-extending-cargo.md | 4 +- ...04-extensible-concurrency-sync-and-send.md | 4 +- src/doc/book/src/ch17-02-trait-objects.md | 22 +- .../ch18-01-all-the-places-for-patterns.md | 15 +- src/doc/book/src/ch19-01-unsafe-rust.md | 35 +- src/doc/book/src/ch19-03-advanced-traits.md | 42 +- src/doc/book/src/ch19-04-advanced-types.md | 16 +- ...ch19-05-advanced-functions-and-closures.md | 6 +- src/doc/book/src/ch19-06-macros.md | 47 +- .../src/ch20-00-final-project-a-web-server.md | 5 +- .../ch20-03-graceful-shutdown-and-cleanup.md | 6 +- src/doc/book/src/title-page.md | 42 +- src/doc/book/tools/megadiff.sh | 22 + src/doc/book/tools/src/bin/link2print.rs | 1 + src/doc/book/tools/src/bin/remove_links.rs | 4 +- ...ng-an-existing-project-to-a-new-edition.md | 2 +- .../cargo-check-for-faster-checking.md | 2 +- .../cargo-new-defaults-to-a-binary-project.md | 2 +- ...tc-for-passing-arbitrary-flags-to-rustc.md | 2 +- .../rust-2018/cargo-and-crates-io/index.md | 3 +- .../loops-can-break-with-a-value.md | 2 +- .../rust-2018/data-types/inclusive-ranges.md | 2 +- .../src/rust-2018/edition-changes.md | 3 - .../src/rust-2018/macros/at-most-once.md | 4 +- .../rust-2018/module-system/path-clarity.md | 4 +- ...emental-compilation-for-faster-compiles.md | 2 +- .../dyn-trait-for-trait-objects.md | 2 +- ...t-for-returning-complex-types-with-ease.md | 4 +- ...e-container-types-support-trait-objects.md | 5 +- src/doc/embedded-book/src/start/qemu.md | 37 +- src/doc/nomicon/src/README.md | 53 +- .../reference/src/attributes/diagnostics.md | 2 +- .../reference/src/conditional-compilation.md | 7 +- src/doc/reference/src/const_eval.md | 3 +- src/doc/reference/src/items/constant-items.md | 35 +- src/doc/reference/src/macros-by-example.md | 10 +- src/doc/reference/src/procedural-macros.md | 2 +- src/doc/reference/src/tokens.md | 19 +- src/doc/reference/src/type-layout.md | 4 + src/doc/rust-by-example/src/SUMMARY.md | 2 +- src/doc/rust-by-example/src/attribute.md | 4 +- src/doc/rust-by-example/src/attribute/cfg.md | 2 +- src/doc/rust-by-example/src/compatibility.md | 2 +- src/doc/rust-by-example/src/conversion.md | 2 +- .../rust-by-example/src/conversion/string.md | 2 +- src/doc/rust-by-example/src/crates/lib.md | 2 +- .../src/custom_types/constants.md | 4 +- .../rust-by-example/src/custom_types/enum.md | 8 +- .../src/custom_types/enum/c_like.md | 2 +- .../src/custom_types/enum/enum_use.md | 4 +- .../custom_types/enum/testcase_linked_list.md | 4 +- .../src/custom_types/structs.md | 4 +- .../multiple_error_types/option_result.md | 2 +- .../reenter_question_mark.md | 1 - .../error/multiple_error_types/wrap_error.md | 2 +- .../src/error/option_unwrap/and_then.md | 2 +- .../src/error/option_unwrap/map.md | 2 +- src/doc/rust-by-example/src/error/result.md | 2 +- .../src/error/result/enter_question_mark.md | 5 +- .../src/error/result/result_alias.md | 2 +- src/doc/rust-by-example/src/flow_control.md | 2 +- .../rust-by-example/src/flow_control/for.md | 2 +- .../src/flow_control/if_let.md | 4 +- .../src/flow_control/match/binding.md | 2 +- .../src/flow_control/match/destructuring.md | 8 +- .../match/destructuring/destructure_enum.md | 4 +- .../destructuring/destructure_structures.md | 2 +- .../match/destructuring/destructure_tuple.md | 2 +- .../src/flow_control/match/guard.md | 2 +- .../src/flow_control/while_let.md | 4 +- .../src/fn/closures/anonymity.md | 2 +- .../src/fn/closures/capture.md | 2 +- .../src/fn/closures/output_parameters.md | 4 +- src/doc/rust-by-example/src/fn/diverging.md | 2 +- src/doc/rust-by-example/src/generics.md | 2 +- .../src/generics/assoc_items/the_problem.md | 4 +- .../src/generics/assoc_items/types.md | 2 +- .../rust-by-example/src/generics/bounds.md | 10 +- .../src/generics/bounds/testcase_empty.md | 2 +- .../rust-by-example/src/generics/gen_fn.md | 4 +- .../rust-by-example/src/generics/gen_trait.md | 4 +- src/doc/rust-by-example/src/generics/impl.md | 6 +- .../src/generics/multi_bounds.md | 4 +- .../rust-by-example/src/generics/new_types.md | 2 +- .../rust-by-example/src/generics/phantom.md | 6 +- .../src/generics/phantom/testcase_units.md | 16 +- src/doc/rust-by-example/src/generics/where.md | 4 +- src/doc/rust-by-example/src/hello.md | 8 +- src/doc/rust-by-example/src/hello/comment.md | 36 +- src/doc/rust-by-example/src/hello/print.md | 26 +- .../rust-by-example/src/hello/print/fmt.md | 4 +- .../src/hello/print/print_debug.md | 6 +- .../src/hello/print/print_display.md | 24 +- .../print/print_display/testcase_list.md | 16 +- src/doc/rust-by-example/src/index.md | 48 +- src/doc/rust-by-example/src/macros.md | 4 +- .../rust-by-example/src/macros/designators.md | 8 +- src/doc/rust-by-example/src/macros/dry.md | 10 +- .../rust-by-example/src/macros/overload.md | 8 +- src/doc/rust-by-example/src/macros/repeat.md | 2 +- src/doc/rust-by-example/src/macros/syntax.md | 6 +- src/doc/rust-by-example/src/mod/split.md | 2 +- .../src/mod/struct_visibility.md | 4 +- src/doc/rust-by-example/src/mod/visibility.md | 2 +- src/doc/rust-by-example/src/primitives.md | 6 +- .../rust-by-example/src/primitives/tuples.md | 2 +- .../rust-by-example/src/scope/borrow/mut.md | 2 +- .../src/scope/lifetime/elision.md | 8 +- .../src/scope/lifetime/explicit.md | 8 +- .../rust-by-example/src/scope/lifetime/fn.md | 4 +- .../src/scope/lifetime/lifetime_bounds.md | 6 +- .../src/scope/lifetime/methods.md | 2 +- .../src/scope/lifetime/static_lifetime.md | 2 +- .../src/scope/lifetime/struct.md | 2 +- .../src/scope/lifetime/trait.md | 2 +- src/doc/rust-by-example/src/scope/move.md | 2 +- src/doc/rust-by-example/src/scope/raii.md | 2 +- src/doc/rust-by-example/src/std.md | 2 +- src/doc/rust-by-example/src/std/box.md | 20 +- src/doc/rust-by-example/src/std_misc.md | 2 +- src/doc/rust-by-example/src/std_misc/fs.md | 2 +- .../std_misc/threads/testcase_mapreduce.md | 12 +- src/doc/rust-by-example/src/testing.md | 8 +- .../src/testing/integration_testing.md | 4 +- .../src/testing/unit_testing.md | 8 +- src/doc/rust-by-example/src/trait/derive.md | 4 +- src/doc/rust-by-example/src/types.md | 8 +- src/doc/rust-by-example/src/types/alias.md | 2 +- src/doc/rust-by-example/src/types/literals.md | 6 +- src/doc/rust-by-example/src/unsafe.md | 2 +- src/doc/rustc-guide/ci/install.sh | 4 +- src/doc/rustc-guide/src/SUMMARY.md | 167 +- src/doc/rustc-guide/src/about-this-guide.md | 12 + .../rustc-guide/src/appendix/bibliography.md | 90 + .../rustc-guide/src/appendix/code-index.md | 4 +- src/doc/rustc-guide/src/appendix/glossary.md | 4 +- .../borrow_check/moves_and_initialization.md | 2 +- .../src/borrow_check/region_inference.md | 488 +- .../region_inference/closure_constraints.md | 10 + .../constraint_propagation.md | 224 + .../region_inference/error_reporting.md | 3 + .../region_inference/lifetime_parameters.md | 125 + .../region_inference/member_constraints.md | 193 + .../placeholders_and_universes.md | 441 + .../src/borrow_check/two_phase_borrows.md | 2 +- src/doc/rustc-guide/src/closure.md | 213 + src/doc/rustc-guide/src/compiler-debugging.md | 15 +- src/doc/rustc-guide/src/compiler-team.md | 2 +- src/doc/rustc-guide/src/conventions.md | 3 +- .../src/debugging-support-in-rustc.md | 321 + .../src/{diag.md => diagnostics.md} | 2 +- .../src/{diag => diagnostics}/json-format.md | 0 .../rustc-guide/src/how-to-build-and-run.md | 293 +- src/doc/rustc-guide/src/img/rustc_stages.svg | 2 + .../src/implementing_new_features.md | 2 +- src/doc/rustc-guide/src/mir/visitor.md | 2 +- .../src/profile-guided-optimization.md | 132 + .../rustc-guide/src/profiling/with_perf.md | 14 +- .../query-evaluation-model-in-detail.md | 2 +- src/doc/rustc-guide/src/query.md | 16 +- .../rustc-guide/src/stabilization_guide.md | 2 +- src/doc/rustc-guide/src/tests/running.md | 21 +- .../rustc-guide/src/traits/chalk-overview.md | 20 +- src/doc/rustc-guide/src/traits/slg.md | 2 +- src/doc/rustc-guide/src/ty.md | 58 +- src/doc/rustc-guide/src/type-inference.md | 11 +- src/doc/rustc-guide/triagebot.toml | 1 + src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/codegen-options/index.md | 17 + src/doc/rustc/src/linker-plugin-lto.md | 5 +- .../src/lints/listing/warn-by-default.md | 21 +- .../rustc/src/profile-guided-optimization.md | 136 + src/doc/rustdoc/src/command-line-arguments.md | 8 +- src/doc/rustdoc/src/passes.md | 4 +- src/doc/rustdoc/src/the-doc-attribute.md | 2 +- .../arbitrary-enum-discriminant.md | 37 + .../src/language-features/asm.md | 2 +- .../src/language-features/box-patterns.md | 2 +- .../src/language-features/box-syntax.md | 2 +- .../src/language-features/generators.md | 2 +- .../src/language-features/global-asm.md | 2 +- .../src/language-features/lang-items.md | 2 +- .../language-features/member-constraints.md | 29 + .../src/language-features/non-ascii-idents.md | 2 +- .../src/language-features/plugin-registrar.md | 2 +- .../src/language-features/plugin.md | 18 +- .../src/language-features/repr-align-enum.md | 42 - .../language-features/transparent-enums.md | 93 + .../language-features/transparent-unions.md | 83 + .../type-alias-enum-variants.md | 36 - .../src/language-features/unboxed-closures.md | 2 +- .../src/language-features/unsized-locals.md | 4 +- .../src/library-features/borrow-state.md | 7 - .../src/library-features/fn-traits.md | 2 +- .../src/library-features/fnbox.md | 32 - .../unstable-book/src/the-unstable-book.md | 2 +- src/etc/cpu-usage-over-time-plot.sh | 49 + src/etc/rust-lldb | 6 +- src/liballoc/alloc.rs | 3 +- src/liballoc/boxed.rs | 171 +- src/liballoc/collections/vec_deque.rs | 31 + src/liballoc/lib.rs | 5 +- src/liballoc/raw_vec.rs | 10 +- src/liballoc/rc.rs | 224 +- src/liballoc/slice.rs | 25 +- src/liballoc/str.rs | 11 +- src/liballoc/sync.rs | 192 +- src/liballoc/{boxed_test.rs => tests.rs} | 0 src/liballoc/tests/vec.rs | 26 +- src/liballoc/vec.rs | 90 +- src/libarena/lib.rs | 254 +- src/libarena/tests.rs | 213 + src/libcore/benches/ascii.rs | 8 +- src/libcore/cell.rs | 59 +- src/libcore/char/convert.rs | 2 +- src/libcore/char/methods.rs | 40 +- src/libcore/convert.rs | 32 +- src/libcore/ffi.rs | 231 +- src/libcore/fmt/mod.rs | 8 +- src/libcore/future/future.rs | 3 +- src/libcore/hash/mod.rs | 6 +- src/libcore/hint.rs | 50 +- src/libcore/internal_macros.rs | 81 - src/libcore/intrinsics.rs | 121 +- src/libcore/iter/adapters/mod.rs | 14 + src/libcore/iter/mod.rs | 5 + src/libcore/iter/range.rs | 76 + src/libcore/iter/traits/accum.rs | 114 +- src/libcore/iter/traits/collect.rs | 2 +- src/libcore/iter/traits/double_ended.rs | 5 +- src/libcore/iter/traits/iterator.rs | 5 +- src/libcore/lib.rs | 5 +- src/libcore/macros.rs | 13 +- src/libcore/marker.rs | 2 +- src/libcore/mem.rs | 1403 -- src/libcore/mem/manually_drop.rs | 146 + src/libcore/mem/maybe_uninit.rs | 533 + src/libcore/mem/mod.rs | 810 + src/libcore/num/f32.rs | 23 +- src/libcore/num/f64.rs | 23 +- src/libcore/num/mod.rs | 55 +- src/libcore/num/wrapping.rs | 4 +- src/libcore/ops/arith.rs | 2 +- src/libcore/ops/deref.rs | 12 +- src/libcore/ops/range.rs | 23 + src/libcore/ops/unsize.rs | 2 +- src/libcore/option.rs | 25 +- src/libcore/pin.rs | 212 +- src/libcore/{ptr.rs => ptr/mod.rs} | 491 +- src/libcore/ptr/non_null.rs | 226 + src/libcore/ptr/unique.rs | 180 + src/libcore/result.rs | 23 +- src/libcore/slice/mod.rs | 215 +- src/libcore/str/mod.rs | 20 + src/libcore/sync/atomic.rs | 16 +- src/libcore/task/wake.rs | 5 +- src/libcore/tests/iter.rs | 87 + src/libcore/tests/lib.rs | 4 +- src/libcore/tests/num/dec2flt/mod.rs | 2 + src/libcore/tests/ops.rs | 17 +- src/libcore/tests/slice.rs | 103 + src/libfmt_macros/Cargo.toml | 3 + src/libfmt_macros/lib.rs | 370 +- src/libfmt_macros/tests.rs | 243 + src/libgraphviz/lib.rs | 383 +- src/libgraphviz/tests.rs | 380 + src/libpanic_unwind/Cargo.toml | 1 + src/libpanic_unwind/dummy.rs | 2 +- src/libpanic_unwind/lib.rs | 5 +- src/libpanic_unwind/macros.rs | 35 - src/libpanic_unwind/seh.rs | 6 +- src/libproc_macro/bridge/rpc.rs | 6 +- src/libprofiler_builtins/build.rs | 10 +- src/librustc/arena.rs | 56 +- src/librustc/cfg/construct.rs | 23 +- src/librustc/cfg/graphviz.rs | 10 +- src/librustc/cfg/mod.rs | 3 +- src/librustc/dep_graph/dep_node.rs | 66 +- src/librustc/dep_graph/graph.rs | 54 +- src/librustc/dep_graph/safe.rs | 3 +- src/librustc/error_codes.rs | 48 +- src/librustc/hir/check_attr.rs | 32 +- src/librustc/hir/def.rs | 28 +- src/librustc/hir/def_id.rs | 2 +- src/librustc/hir/intravisit.rs | 37 +- src/librustc/hir/itemlikevisit.rs | 2 +- src/librustc/hir/lowering.rs | 1600 +- src/librustc/hir/map/blocks.rs | 4 +- src/librustc/hir/map/collector.rs | 21 +- src/librustc/hir/map/def_collector.rs | 50 +- src/librustc/hir/map/definitions.rs | 54 +- src/librustc/hir/map/hir_id_validator.rs | 31 +- src/librustc/hir/map/mod.rs | 415 +- src/librustc/hir/mod.rs | 474 +- src/librustc/hir/print.rs | 150 +- src/librustc/hir/upvars.rs | 104 + src/librustc/ich/hcx.rs | 17 +- src/librustc/ich/impls_hir.rs | 12 +- src/librustc/ich/impls_syntax.rs | 183 +- src/librustc/ich/impls_ty.rs | 73 +- src/librustc/infer/at.rs | 41 +- src/librustc/infer/canonical/canonicalizer.rs | 78 +- src/librustc/infer/canonical/mod.rs | 73 +- .../infer/canonical/query_response.rs | 83 +- src/librustc/infer/canonical/substitute.rs | 6 +- src/librustc/infer/combine.rs | 50 +- src/librustc/infer/equate.rs | 19 +- src/librustc/infer/error_reporting/mod.rs | 72 +- .../infer/error_reporting/need_type_info.rs | 155 +- .../nice_region_error/different_lifetimes.rs | 6 +- .../nice_region_error/find_anon_type.rs | 32 +- .../error_reporting/nice_region_error/mod.rs | 14 +- .../nice_region_error/named_anon_conflict.rs | 4 +- .../nice_region_error/outlives_closure.rs | 6 +- .../nice_region_error/placeholder_error.rs | 22 +- .../nice_region_error/static_impl_trait.rs | 2 +- .../error_reporting/nice_region_error/util.rs | 10 +- src/librustc/infer/error_reporting/note.rs | 6 +- src/librustc/infer/freshen.rs | 17 +- src/librustc/infer/fudge.rs | 12 +- src/librustc/infer/glb.rs | 25 +- src/librustc/infer/higher_ranked/mod.rs | 4 +- src/librustc/infer/lattice.rs | 28 +- .../infer/lexical_region_resolve/graphviz.rs | 34 +- .../infer/lexical_region_resolve/mod.rs | 362 +- src/librustc/infer/lub.rs | 25 +- src/librustc/infer/mod.rs | 137 +- src/librustc/infer/nll_relate/mod.rs | 45 +- src/librustc/infer/opaque_types/mod.rs | 596 +- src/librustc/infer/outlives/env.rs | 13 +- .../infer/outlives/free_region_map.rs | 17 +- src/librustc/infer/outlives/obligations.rs | 18 +- src/librustc/infer/outlives/verify.rs | 14 +- .../infer/region_constraints/leak_check.rs | 4 +- src/librustc/infer/region_constraints/mod.rs | 131 +- src/librustc/infer/resolve.rs | 82 +- src/librustc/infer/sub.rs | 19 +- src/librustc/infer/type_variable.rs | 37 +- src/librustc/infer/unify_key.rs | 27 +- src/librustc/lib.rs | 2 +- src/librustc/lint/builtin.rs | 9 +- src/librustc/lint/context.rs | 106 +- src/librustc/lint/internal.rs | 28 +- src/librustc/lint/levels.rs | 33 +- src/librustc/lint/mod.rs | 33 +- src/librustc/macros.rs | 32 +- src/librustc/middle/cstore.rs | 12 +- src/librustc/middle/dead.rs | 52 +- src/librustc/middle/dependency_format.rs | 20 +- src/librustc/middle/entry.rs | 11 +- src/librustc/middle/exported_symbols.rs | 13 +- src/librustc/middle/expr_use_visitor.rs | 86 +- src/librustc/middle/free_region.rs | 8 +- src/librustc/middle/intrinsicck.rs | 24 +- src/librustc/middle/lang_items.rs | 19 +- src/librustc/middle/lib_features.rs | 12 +- src/librustc/middle/liveness.rs | 120 +- src/librustc/middle/mem_categorization.rs | 140 +- src/librustc/middle/reachable.rs | 42 +- src/librustc/middle/recursion_limit.rs | 2 +- src/librustc/middle/region.rs | 257 +- src/librustc/middle/resolve_lifetime.rs | 140 +- src/librustc/middle/stability.rs | 56 +- src/librustc/middle/weak_lang_items.rs | 14 +- src/librustc/mir/cache.rs | 12 +- src/librustc/mir/interpret/allocation.rs | 191 +- src/librustc/mir/interpret/error.rs | 79 +- src/librustc/mir/interpret/mod.rs | 138 +- src/librustc/mir/interpret/pointer.rs | 104 +- src/librustc/mir/interpret/value.rs | 354 +- src/librustc/mir/mod.rs | 396 +- src/librustc/mir/mono.rs | 313 +- src/librustc/mir/tcx.rs | 63 +- src/librustc/mir/traversal.rs | 56 +- src/librustc/mir/visit.rs | 101 +- src/librustc/query/mod.rs | 234 +- src/librustc/session/config.rs | 854 +- src/librustc/session/config/tests.rs | 706 + src/librustc/session/mod.rs | 100 +- src/librustc/traits/auto_trait.rs | 151 +- src/librustc/traits/chalk_fulfill.rs | 14 +- src/librustc/traits/codegen/mod.rs | 43 +- src/librustc/traits/coherence.rs | 62 +- src/librustc/traits/engine.rs | 16 +- src/librustc/traits/error_reporting.rs | 138 +- src/librustc/traits/fulfill.rs | 129 +- src/librustc/traits/mod.rs | 124 +- src/librustc/traits/object_safety.rs | 26 +- src/librustc/traits/on_unimplemented.rs | 120 +- src/librustc/traits/project.rs | 300 +- src/librustc/traits/query/dropck_outlives.rs | 15 +- .../traits/query/evaluate_obligation.rs | 2 +- src/librustc/traits/query/normalize.rs | 23 +- .../traits/query/normalize_erasing_regions.rs | 10 +- src/librustc/traits/query/outlives_bounds.rs | 2 +- .../traits/query/type_op/ascribe_user_type.rs | 12 +- src/librustc/traits/query/type_op/custom.rs | 28 +- src/librustc/traits/query/type_op/eq.rs | 12 +- .../query/type_op/implied_outlives_bounds.rs | 12 +- src/librustc/traits/query/type_op/mod.rs | 52 +- .../traits/query/type_op/normalize.rs | 80 +- src/librustc/traits/query/type_op/outlives.rs | 15 +- .../traits/query/type_op/prove_predicate.rs | 12 +- src/librustc/traits/query/type_op/subtype.rs | 12 +- src/librustc/traits/select.rs | 151 +- src/librustc/traits/specialize/mod.rs | 53 +- .../traits/specialize/specialization_graph.rs | 64 +- src/librustc/traits/structural_impls.rs | 42 +- src/librustc/traits/util.rs | 395 +- src/librustc/ty/_match.rs | 12 +- src/librustc/ty/adjustment.rs | 7 +- src/librustc/ty/codec.rs | 96 +- src/librustc/ty/constness.rs | 42 +- src/librustc/ty/context.rs | 460 +- src/librustc/ty/erase_regions.rs | 18 +- src/librustc/ty/error.rs | 46 +- src/librustc/ty/fast_reject.rs | 16 +- src/librustc/ty/fold.rs | 128 +- .../ty/inhabitedness/def_id_forest.rs | 25 +- src/librustc/ty/inhabitedness/mod.rs | 29 +- src/librustc/ty/instance.rs | 128 +- src/librustc/ty/layout.rs | 929 +- src/librustc/ty/mod.rs | 460 +- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/print/mod.rs | 34 +- src/librustc/ty/print/obsolete.rs | 282 + src/librustc/ty/print/pretty.rs | 291 +- src/librustc/ty/query/config.rs | 61 +- src/librustc/ty/query/job.rs | 18 +- src/librustc/ty/query/keys.rs | 51 +- src/librustc/ty/query/mod.rs | 9 +- src/librustc/ty/query/on_disk_cache.rs | 258 +- src/librustc/ty/query/plumbing.rs | 248 +- src/librustc/ty/query/values.rs | 18 +- src/librustc/ty/relate.rs | 492 +- src/librustc/ty/steal.rs | 6 +- src/librustc/ty/structural_impls.rs | 179 +- src/librustc/ty/sty.rs | 290 +- src/librustc/ty/subst.rs | 83 +- src/librustc/ty/trait_def.rs | 19 +- src/librustc/ty/util.rs | 132 +- src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 57 +- src/librustc/util/captures.rs | 2 + src/librustc/util/common.rs | 48 +- src/librustc/util/profiling.rs | 17 +- src/librustc_allocator/expand.rs | 32 +- src/librustc_allocator/lib.rs | 1 + src/librustc_borrowck/borrowck/check_loans.rs | 25 +- .../borrowck/gather_loans/gather_moves.rs | 32 +- .../borrowck/gather_loans/lifetime.rs | 2 +- .../borrowck/gather_loans/mod.rs | 5 +- .../borrowck/gather_loans/move_error.rs | 2 +- .../borrowck/gather_loans/restrictions.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 115 +- src/librustc_borrowck/borrowck/move_data.rs | 94 +- src/librustc_borrowck/dataflow.rs | 46 +- src/librustc_borrowck/graphviz.rs | 17 +- src/librustc_borrowck/lib.rs | 2 + src/librustc_codegen_llvm/Cargo.toml | 2 +- src/librustc_codegen_llvm/allocator.rs | 2 +- src/librustc_codegen_llvm/asm.rs | 2 +- src/librustc_codegen_llvm/attributes.rs | 13 +- src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_llvm/back/write.rs | 16 +- src/librustc_codegen_llvm/base.rs | 45 +- src/librustc_codegen_llvm/builder.rs | 397 +- src/librustc_codegen_llvm/callee.rs | 3 +- src/librustc_codegen_llvm/common.rs | 21 +- src/librustc_codegen_llvm/consts.rs | 36 +- src/librustc_codegen_llvm/context.rs | 44 +- .../debuginfo/create_scope_map.rs | 6 +- .../debuginfo/metadata.rs | 88 +- src/librustc_codegen_llvm/debuginfo/mod.rs | 11 +- .../debuginfo/namespace.rs | 3 +- src/librustc_codegen_llvm/intrinsic.rs | 87 +- src/librustc_codegen_llvm/lib.rs | 40 +- src/librustc_codegen_llvm/llvm/ffi.rs | 34 +- src/librustc_codegen_llvm/mono_item.rs | 3 +- src/librustc_codegen_llvm/type_.rs | 2 +- src/librustc_codegen_llvm/type_of.rs | 6 +- src/librustc_codegen_llvm/va_arg.rs | 12 +- src/librustc_codegen_ssa/Cargo.toml | 3 +- src/librustc_codegen_ssa/README.md | 12 +- src/librustc_codegen_ssa/back/link.rs | 83 +- src/librustc_codegen_ssa/back/linker.rs | 27 +- src/librustc_codegen_ssa/back/rpath.rs | 96 +- src/librustc_codegen_ssa/back/rpath/tests.rs | 93 + .../back/symbol_export.rs | 66 +- src/librustc_codegen_ssa/back/write.rs | 46 +- src/librustc_codegen_ssa/base.rs | 135 +- src/librustc_codegen_ssa/common.rs | 22 +- .../debuginfo/type_names.rs | 37 +- src/librustc_codegen_ssa/glue.rs | 4 +- src/librustc_codegen_ssa/lib.rs | 3 +- src/librustc_codegen_ssa/meth.rs | 7 +- src/librustc_codegen_ssa/mir/analyze.rs | 21 +- src/librustc_codegen_ssa/mir/block.rs | 42 +- src/librustc_codegen_ssa/mir/constant.rs | 17 +- src/librustc_codegen_ssa/mir/mod.rs | 82 +- src/librustc_codegen_ssa/mir/operand.rs | 104 +- src/librustc_codegen_ssa/mir/place.rs | 83 +- src/librustc_codegen_ssa/mir/rvalue.rs | 17 +- src/librustc_codegen_ssa/mir/statement.rs | 2 +- src/librustc_codegen_ssa/mono_item.rs | 26 +- src/librustc_codegen_ssa/traits/asm.rs | 2 +- src/librustc_codegen_ssa/traits/backend.rs | 19 +- src/librustc_codegen_ssa/traits/builder.rs | 10 +- src/librustc_codegen_ssa/traits/consts.rs | 1 + src/librustc_codegen_ssa/traits/debuginfo.rs | 7 +- src/librustc_codegen_ssa/traits/declare.rs | 3 +- src/librustc_codegen_ssa/traits/intrinsic.rs | 4 +- src/librustc_codegen_ssa/traits/misc.rs | 5 +- src/librustc_codegen_ssa/traits/mod.rs | 4 +- src/librustc_codegen_ssa/traits/statics.rs | 2 +- src/librustc_codegen_ssa/traits/type_.rs | 2 +- src/librustc_codegen_utils/Cargo.toml | 3 +- src/librustc_codegen_utils/codegen_backend.rs | 7 +- src/librustc_codegen_utils/lib.rs | 6 +- src/librustc_codegen_utils/symbol_names.rs | 544 +- .../symbol_names/legacy.rs | 460 + src/librustc_codegen_utils/symbol_names/v0.rs | 656 + .../symbol_names_test.rs | 21 +- src/librustc_data_structures/Cargo.toml | 1 + .../binary_search_util/mod.rs | 49 + .../binary_search_util/test.rs | 23 + src/librustc_data_structures/bit_set.rs | 236 +- src/librustc_data_structures/fingerprint.rs | 4 +- src/librustc_data_structures/fx.rs | 5 + .../graph/iterate/mod.rs | 36 +- src/librustc_data_structures/graph/mod.rs | 12 + src/librustc_data_structures/graph/scc/mod.rs | 46 +- .../graph/vec_graph/mod.rs | 113 + .../graph/vec_graph/test.rs | 51 + src/librustc_data_structures/indexed_vec.rs | 22 +- src/librustc_data_structures/lib.rs | 1 + src/librustc_data_structures/macros.rs | 12 +- .../obligation_forest/mod.rs | 2 +- .../owning_ref/mod.rs | 715 +- .../owning_ref/tests.rs | 712 + src/librustc_data_structures/sip128.rs | 8 +- src/librustc_data_structures/sorted_map.rs | 202 +- .../sorted_map/tests.rs | 199 + src/librustc_data_structures/stable_hasher.rs | 43 +- src/librustc_data_structures/thin_vec.rs | 6 + .../transitive_relation.rs | 4 + .../vec_linked_list.rs | 2 +- src/librustc_driver/lib.rs | 1 + src/librustc_driver/pretty.rs | 83 +- src/librustc_errors/Cargo.toml | 1 + .../annotate_snippet_emitter_writer.rs | 212 + src/librustc_errors/diagnostic.rs | 2 +- src/librustc_errors/diagnostic_builder.rs | 2 +- src/librustc_errors/emitter.rs | 364 +- src/librustc_errors/lib.rs | 35 +- src/librustc_errors/lock.rs | 2 +- src/librustc_errors/snippet.rs | 1 - src/librustc_incremental/assert_dep_graph.rs | 21 +- .../assert_module_sources.rs | 8 +- src/librustc_incremental/lib.rs | 2 + .../persist/dirty_clean.rs | 26 +- src/librustc_incremental/persist/load.rs | 2 +- src/librustc_incremental/persist/save.rs | 8 +- src/librustc_interface/interface.rs | 6 +- src/librustc_interface/lib.rs | 1 + src/librustc_interface/passes.rs | 32 +- src/librustc_interface/proc_macro_decls.rs | 7 +- src/librustc_interface/util.rs | 25 +- src/librustc_lint/builtin.rs | 363 +- src/librustc_lint/lib.rs | 9 +- src/librustc_lint/nonstandard_style.rs | 26 +- src/librustc_lint/nonstandard_style/tests.rs | 21 + src/librustc_lint/types.rs | 167 +- src/librustc_lint/unused.rs | 193 +- src/librustc_llvm/build.rs | 15 + src/librustc_macros/Cargo.toml | 2 +- src/librustc_macros/src/lib.rs | 2 + src/librustc_macros/src/query.rs | 120 +- src/librustc_macros/src/symbols.rs | 39 +- src/librustc_metadata/Cargo.toml | 1 + src/librustc_metadata/creader.rs | 64 +- src/librustc_metadata/cstore.rs | 6 +- src/librustc_metadata/cstore_impl.rs | 122 +- src/librustc_metadata/decoder.rs | 246 +- src/librustc_metadata/dynamic_lib.rs | 56 +- src/librustc_metadata/dynamic_lib/tests.rs | 47 + src/librustc_metadata/encoder.rs | 394 +- src/librustc_metadata/foreign_modules.rs | 10 +- src/librustc_metadata/index.rs | 17 +- src/librustc_metadata/index_builder.rs | 224 - src/librustc_metadata/isolated_encoder.rs | 48 - src/librustc_metadata/lib.rs | 4 +- src/librustc_metadata/link_args.rs | 4 +- src/librustc_metadata/native_libs.rs | 12 +- src/librustc_metadata/schema.rs | 245 +- src/librustc_mir/borrow_check/borrow_set.rs | 39 +- .../borrow_check/conflict_errors.rs | 1976 ++ .../borrow_check/error_reporting.rs | 2076 +-- src/librustc_mir/borrow_check/flows.rs | 20 +- src/librustc_mir/borrow_check/location.rs | 6 +- src/librustc_mir/borrow_check/mod.rs | 218 +- src/librustc_mir/borrow_check/move_errors.rs | 561 +- .../borrow_check/mutability_errors.rs | 116 +- .../borrow_check/nll/constraint_generation.rs | 18 +- .../borrow_check/nll/constraints/graph.rs | 26 +- .../borrow_check/nll/constraints/mod.rs | 37 +- .../nll/explain_borrow/find_use.rs | 30 +- .../borrow_check/nll/explain_borrow/mod.rs | 48 +- src/librustc_mir/borrow_check/nll/facts.rs | 4 +- .../borrow_check/nll/invalidation.rs | 32 +- .../borrow_check/nll/member_constraints.rs | 235 + src/librustc_mir/borrow_check/nll/mod.rs | 61 +- .../borrow_check/nll/region_infer/dump_mir.rs | 2 +- .../nll/region_infer/error_reporting/mod.rs | 112 +- .../error_reporting/region_name.rs | 80 +- .../region_infer/error_reporting/var_name.rs | 29 +- .../borrow_check/nll/region_infer/graphviz.rs | 6 +- .../borrow_check/nll/region_infer/mod.rs | 607 +- .../borrow_check/nll/region_infer/values.rs | 14 +- src/librustc_mir/borrow_check/nll/renumber.rs | 29 +- .../nll/type_check/constraint_conversion.rs | 43 +- .../nll/type_check/free_region_relations.rs | 23 +- .../nll/type_check/input_output.rs | 28 +- .../nll/type_check/liveness/local_use_map.rs | 10 +- .../nll/type_check/liveness/mod.rs | 28 +- .../nll/type_check/liveness/trace.rs | 66 +- .../borrow_check/nll/type_check/mod.rs | 454 +- .../borrow_check/nll/type_check/relate_tys.rs | 12 +- .../borrow_check/nll/universal_regions.rs | 24 +- src/librustc_mir/borrow_check/path_utils.rs | 42 +- src/librustc_mir/borrow_check/place_ext.rs | 82 +- .../borrow_check/places_conflict.rs | 52 +- src/librustc_mir/borrow_check/prefixes.rs | 23 +- src/librustc_mir/borrow_check/used_muts.rs | 42 +- src/librustc_mir/build/block.rs | 54 +- src/librustc_mir/build/expr/as_constant.rs | 2 +- src/librustc_mir/build/expr/as_operand.rs | 6 +- src/librustc_mir/build/expr/as_place.rs | 20 +- src/librustc_mir/build/expr/as_rvalue.rs | 40 +- src/librustc_mir/build/expr/as_temp.rs | 42 +- src/librustc_mir/build/expr/into.rs | 29 +- src/librustc_mir/build/expr/stmt.rs | 149 +- src/librustc_mir/build/into.rs | 35 +- src/librustc_mir/build/matches/mod.rs | 505 +- src/librustc_mir/build/matches/simplify.rs | 2 +- src/librustc_mir/build/matches/test.rs | 484 +- src/librustc_mir/build/matches/util.rs | 35 +- src/librustc_mir/build/misc.rs | 8 +- src/librustc_mir/build/mod.rs | 314 +- src/librustc_mir/build/scope.rs | 707 +- src/librustc_mir/const_eval.rs | 318 +- src/librustc_mir/dataflow/at_location.rs | 110 +- .../dataflow/drop_flag_effects.rs | 135 +- src/librustc_mir/dataflow/graphviz.rs | 57 +- .../dataflow/impls/borrowed_locals.rs | 87 +- src/librustc_mir/dataflow/impls/borrows.rs | 150 +- src/librustc_mir/dataflow/impls/mod.rs | 299 +- .../dataflow/impls/storage_liveness.rs | 165 +- src/librustc_mir/dataflow/mod.rs | 517 +- .../dataflow/move_paths/builder.rs | 193 +- src/librustc_mir/dataflow/move_paths/mod.rs | 47 +- src/librustc_mir/error_codes.rs | 32 + src/librustc_mir/hair/constant.rs | 47 +- src/librustc_mir/hair/cx/block.rs | 21 +- src/librustc_mir/hair/cx/expr.rs | 167 +- src/librustc_mir/hair/cx/mod.rs | 68 +- src/librustc_mir/hair/cx/to_ref.rs | 21 +- src/librustc_mir/hair/mod.rs | 27 +- src/librustc_mir/hair/pattern/_match.rs | 268 +- src/librustc_mir/hair/pattern/check_match.rs | 23 +- src/librustc_mir/hair/pattern/mod.rs | 111 +- src/librustc_mir/hair/util.rs | 4 +- src/librustc_mir/interpret/cast.rs | 164 +- src/librustc_mir/interpret/eval_context.rs | 151 +- src/librustc_mir/interpret/intern.rs | 335 + src/librustc_mir/interpret/intrinsics.rs | 27 +- .../interpret/intrinsics/type_name.rs | 235 + src/librustc_mir/interpret/machine.rs | 128 +- src/librustc_mir/interpret/memory.rs | 524 +- src/librustc_mir/interpret/mod.rs | 7 +- src/librustc_mir/interpret/operand.rs | 256 +- src/librustc_mir/interpret/operator.rs | 121 +- src/librustc_mir/interpret/place.rs | 240 +- src/librustc_mir/interpret/snapshot.rs | 66 +- src/librustc_mir/interpret/step.rs | 18 +- src/librustc_mir/interpret/terminator.rs | 62 +- src/librustc_mir/interpret/traits.rs | 49 +- src/librustc_mir/interpret/validity.rs | 208 +- src/librustc_mir/interpret/visitor.rs | 84 +- src/librustc_mir/lib.rs | 9 +- src/librustc_mir/lints.rs | 32 +- src/librustc_mir/monomorphize/collector.rs | 250 +- src/librustc_mir/monomorphize/item.rs | 334 +- src/librustc_mir/monomorphize/mod.rs | 142 +- src/librustc_mir/monomorphize/partitioning.rs | 284 +- src/librustc_mir/shim.rs | 223 +- src/librustc_mir/transform/add_call_guards.rs | 17 +- .../transform/add_moves_for_packed_drops.rs | 55 +- src/librustc_mir/transform/add_retag.rs | 14 +- src/librustc_mir/transform/check_unsafety.rs | 164 +- .../transform/cleanup_post_borrowck.rs | 9 +- src/librustc_mir/transform/const_prop.rs | 397 +- src/librustc_mir/transform/copy_prop.rs | 53 +- src/librustc_mir/transform/deaggregator.rs | 75 +- src/librustc_mir/transform/dump_mir.rs | 31 +- src/librustc_mir/transform/elaborate_drops.rs | 138 +- src/librustc_mir/transform/erase_regions.rs | 17 +- src/librustc_mir/transform/generator.rs | 684 +- src/librustc_mir/transform/inline.rs | 182 +- src/librustc_mir/transform/instcombine.rs | 34 +- src/librustc_mir/transform/lower_128bit.rs | 40 +- src/librustc_mir/transform/mod.rs | 84 +- src/librustc_mir/transform/no_landing_pads.rs | 11 +- src/librustc_mir/transform/promote_consts.rs | 54 +- src/librustc_mir/transform/qualify_consts.rs | 463 +- .../transform/qualify_min_const_fn.rs | 123 +- .../transform/remove_noop_landing_pads.rs | 38 +- src/librustc_mir/transform/rustc_peek.rs | 94 +- src/librustc_mir/transform/simplify.rs | 58 +- .../transform/simplify_branches.rs | 7 +- .../transform/uniform_array_move_out.rs | 61 +- src/librustc_mir/util/aggregate.rs | 76 + src/librustc_mir/util/alignment.rs | 22 +- src/librustc_mir/util/borrowck_errors.rs | 22 +- src/librustc_mir/util/collect_writes.rs | 6 +- src/librustc_mir/util/def_use.rs | 20 +- src/librustc_mir/util/elaborate_drops.rs | 126 +- src/librustc_mir/util/graphviz.rs | 78 +- src/librustc_mir/util/liveness.rs | 63 +- src/librustc_mir/util/mod.rs | 7 +- src/librustc_mir/util/patch.rs | 40 +- src/librustc_mir/util/pretty.rs | 140 +- src/librustc_passes/ast_validation.rs | 210 +- src/librustc_passes/hir_stats.rs | 8 +- src/librustc_passes/layout_test.rs | 24 +- src/librustc_passes/lib.rs | 3 + src/librustc_passes/loops.rs | 10 +- src/librustc_passes/rvalue_promotion.rs | 37 +- src/librustc_plugin/build.rs | 7 +- src/librustc_plugin/load.rs | 12 +- src/librustc_plugin/registry.rs | 49 +- src/librustc_privacy/lib.rs | 252 +- src/librustc_resolve/Cargo.toml | 1 + src/librustc_resolve/build_reduced_graph.rs | 49 +- src/librustc_resolve/check_unused.rs | 2 +- src/librustc_resolve/diagnostics.rs | 18 +- src/librustc_resolve/lib.rs | 469 +- src/librustc_resolve/macros.rs | 84 +- src/librustc_resolve/resolve_imports.rs | 38 +- src/librustc_save_analysis/dump_visitor.rs | 38 +- src/librustc_save_analysis/lib.rs | 84 +- src/librustc_save_analysis/sig.rs | 4 +- src/librustc_save_analysis/span_utils.rs | 28 +- src/librustc_target/Cargo.toml | 1 + src/librustc_target/abi/call/x86_64.rs | 33 +- src/librustc_target/abi/mod.rs | 23 +- src/librustc_target/lib.rs | 1 + src/librustc_target/spec/fuchsia_base.rs | 2 +- src/librustc_target/spec/mod.rs | 30 +- src/librustc_target/spec/netbsd_base.rs | 3 - .../spec/riscv32imac_unknown_none_elf.rs | 1 + .../spec/riscv32imc_unknown_none_elf.rs | 1 + .../spec/riscv64gc_unknown_none_elf.rs | 1 + .../spec/riscv64imac_unknown_none_elf.rs | 1 + src/librustc_target/spec/solaris_base.rs | 1 + src/librustc_target/spec/wasm32_base.rs | 5 + .../spec/wasm32_experimental_emscripten.rs | 1 + .../spec/wasm32_unknown_emscripten.rs | 1 + src/librustc_traits/chalk_context/mod.rs | 141 +- .../chalk_context/program_clauses/builtin.rs | 16 +- .../chalk_context/program_clauses/mod.rs | 12 +- .../program_clauses/primitive.rs | 30 +- .../chalk_context/resolvent_ops.rs | 24 +- src/librustc_traits/chalk_context/unify.rs | 19 +- src/librustc_traits/dropck_outlives.rs | 10 +- src/librustc_traits/evaluate_obligation.rs | 2 +- src/librustc_traits/generic_types.rs | 18 +- .../implied_outlives_bounds.rs | 12 +- src/librustc_traits/lib.rs | 1 + src/librustc_traits/lowering/environment.rs | 21 +- src/librustc_traits/lowering/mod.rs | 49 +- .../normalize_erasing_regions.rs | 7 +- .../normalize_projection_ty.rs | 2 +- src/librustc_traits/type_op.rs | 28 +- src/librustc_typeck/astconv.rs | 997 +- src/librustc_typeck/check/_match.rs | 209 +- src/librustc_typeck/check/autoderef.rs | 52 +- src/librustc_typeck/check/callee.rs | 55 +- src/librustc_typeck/check/cast.rs | 99 +- src/librustc_typeck/check/closure.rs | 25 +- src/librustc_typeck/check/coercion.rs | 112 +- src/librustc_typeck/check/compare_method.rs | 206 +- src/librustc_typeck/check/demand.rs | 86 +- src/librustc_typeck/check/dropck.rs | 19 +- src/librustc_typeck/check/expr.rs | 1568 ++ .../check/generator_interior.rs | 69 +- src/librustc_typeck/check/intrinsic.rs | 60 +- src/librustc_typeck/check/method/confirm.rs | 39 +- src/librustc_typeck/check/method/mod.rs | 43 +- src/librustc_typeck/check/method/probe.rs | 157 +- src/librustc_typeck/check/method/suggest.rs | 67 +- src/librustc_typeck/check/mod.rs | 2289 +-- src/librustc_typeck/check/op.rs | 90 +- src/librustc_typeck/check/regionck.rs | 62 +- src/librustc_typeck/check/upvar.rs | 43 +- src/librustc_typeck/check/wfcheck.rs | 292 +- src/librustc_typeck/check/writeback.rs | 184 +- src/librustc_typeck/check_unused.rs | 20 +- src/librustc_typeck/coherence/builtin.rs | 50 +- .../coherence/inherent_impls.rs | 39 +- .../coherence/inherent_impls_overlap.rs | 11 +- src/librustc_typeck/coherence/mod.rs | 20 +- src/librustc_typeck/coherence/orphan.rs | 10 +- src/librustc_typeck/coherence/unsafety.rs | 10 +- src/librustc_typeck/collect.rs | 775 +- .../constrained_generic_params.rs | 22 +- src/librustc_typeck/error_codes.rs | 146 +- src/librustc_typeck/impl_wf_check.rs | 31 +- src/librustc_typeck/lib.rs | 82 +- src/librustc_typeck/namespace.rs | 12 +- src/librustc_typeck/outlives/explicit.rs | 2 +- .../outlives/implicit_infer.rs | 12 +- src/librustc_typeck/outlives/mod.rs | 13 +- src/librustc_typeck/outlives/test.rs | 8 +- src/librustc_typeck/outlives/utils.rs | 4 +- src/librustc_typeck/variance/constraints.rs | 4 +- src/librustc_typeck/variance/mod.rs | 13 +- src/librustc_typeck/variance/solve.rs | 2 +- src/librustc_typeck/variance/terms.rs | 15 +- src/librustc_typeck/variance/test.rs | 8 +- src/librustdoc/Cargo.toml | 1 + src/librustdoc/clean/auto_trait.rs | 42 +- src/librustdoc/clean/cfg.rs | 18 +- src/librustdoc/clean/inline.rs | 16 +- src/librustdoc/clean/mod.rs | 445 +- src/librustdoc/clean/simplify.rs | 4 +- src/librustdoc/core.rs | 21 +- src/librustdoc/docfs.rs | 116 + src/librustdoc/doctree.rs | 204 +- src/librustdoc/html/format.rs | 57 +- src/librustdoc/html/highlight.rs | 60 +- src/librustdoc/html/item_type.rs | 17 +- src/librustdoc/html/markdown.rs | 165 +- src/librustdoc/html/markdown/tests.rs | 125 + src/librustdoc/html/render.rs | 356 +- src/librustdoc/html/static/main.js | 17 +- src/librustdoc/html/toc.rs | 83 +- src/librustdoc/html/toc/tests.rs | 80 + src/librustdoc/lib.rs | 13 +- .../passes/check_code_block_syntax.rs | 12 +- .../passes/collect_intra_doc_links.rs | 42 +- src/librustdoc/passes/mod.rs | 10 +- src/librustdoc/test.rs | 456 +- src/librustdoc/test/tests.rs | 299 + src/librustdoc/theme.rs | 28 +- src/librustdoc/visit_ast.rs | 253 +- src/libserialize/Cargo.toml | 1 + src/libserialize/collection_impls.rs | 69 + src/libserialize/hex.rs | 77 +- src/libserialize/hex/tests.rs | 74 + src/libserialize/json.rs | 153 +- src/libserialize/json/tests.rs | 134 + src/libserialize/leb128.rs | 2 +- src/libserialize/opaque.rs | 4 +- src/libserialize/serialize.rs | 33 +- src/libstd/Cargo.toml | 24 +- src/libstd/env.rs | 4 +- src/libstd/error.rs | 30 +- src/libstd/f32.rs | 2 +- src/libstd/f64.rs | 2 +- src/libstd/ffi/mod.rs | 2 +- src/libstd/fs.rs | 2 +- src/libstd/future.rs | 6 + src/libstd/io/buffered.rs | 41 +- src/libstd/io/mod.rs | 11 +- src/libstd/lib.rs | 7 +- src/libstd/macros.rs | 38 +- src/libstd/net/ip.rs | 944 +- src/libstd/os/mod.rs | 2 +- src/libstd/panicking.rs | 9 +- src/libstd/primitive_docs.rs | 20 +- src/libstd/process.rs | 5 +- src/libstd/sync/mod.rs | 1 + src/libstd/sync/once.rs | 5 + src/libstd/sys/cloudabi/backtrace.rs | 116 - src/libstd/sys/cloudabi/mod.rs | 2 - src/libstd/sys/mod.rs | 6 +- src/libstd/sys/redox/backtrace/mod.rs | 32 - src/libstd/sys/redox/backtrace/printing.rs | 1 - src/libstd/sys/redox/backtrace/tracing.rs | 99 - src/libstd/sys/redox/ext/fs.rs | 2 +- src/libstd/sys/redox/fast_thread_local.rs | 109 +- src/libstd/sys/redox/mod.rs | 2 - src/libstd/sys/redox/process.rs | 65 +- src/libstd/sys/sgx/backtrace.rs | 98 - src/libstd/sys/sgx/mod.rs | 2 - src/libstd/sys/unix/backtrace/mod.rs | 110 - .../sys/unix/backtrace/printing/dladdr.rs | 34 - src/libstd/sys/unix/backtrace/printing/mod.rs | 33 - .../unix/backtrace/tracing/backtrace_fn.rs | 39 - .../sys/unix/backtrace/tracing/gcc_s.rs | 99 - src/libstd/sys/unix/backtrace/tracing/mod.rs | 8 - src/libstd/sys/unix/condvar.rs | 12 +- src/libstd/sys/unix/ext/fs.rs | 2 +- src/libstd/sys/unix/ext/net.rs | 11 +- src/libstd/sys/unix/fast_thread_local.rs | 4 - src/libstd/sys/unix/mod.rs | 2 - src/libstd/sys/unix/mutex.rs | 24 +- src/libstd/sys/unix/process/process_common.rs | 14 +- src/libstd/sys/unix/process/process_unix.rs | 92 +- src/libstd/sys/wasi/args.rs | 2 +- src/libstd/sys/wasi/backtrace.rs | 27 - src/libstd/sys/wasi/mod.rs | 2 - src/libstd/sys/wasm/backtrace.rs | 27 - src/libstd/sys/wasm/mod.rs | 4 +- src/libstd/sys/wasm/thread.rs | 2 +- src/libstd/sys/wasm/thread_local_atomics.rs | 2 +- .../sys/windows/backtrace/backtrace_gnu.rs | 53 - src/libstd/sys/windows/backtrace/mod.rs | 355 - .../sys/windows/backtrace/printing/mod.rs | 24 - .../sys/windows/backtrace/printing/msvc.rs | 208 - src/libstd/sys/windows/c.rs | 371 - src/libstd/sys/windows/dynamic_lib.rs | 44 - src/libstd/sys/windows/fast_thread_local.rs | 4 - src/libstd/sys/windows/mod.rs | 4 - src/libstd/sys_common/backtrace.rs | 304 +- src/libstd/sys_common/gnu/libbacktrace.rs | 175 - src/libstd/sys_common/gnu/mod.rs | 5 - src/libstd/sys_common/mod.rs | 8 +- src/libstd/thread/local.rs | 290 +- src/libsyntax/ast.rs | 185 +- src/libsyntax/attr/builtin.rs | 16 +- src/libsyntax/attr/mod.rs | 68 +- src/libsyntax/config.rs | 60 +- src/libsyntax/diagnostics/plugin.rs | 65 +- src/libsyntax/early_buffered_lints.rs | 4 +- src/libsyntax/ext/base.rs | 348 +- src/libsyntax/ext/build.rs | 105 +- src/libsyntax/ext/derive.rs | 34 +- src/libsyntax/ext/expand.rs | 275 +- src/libsyntax/ext/placeholders.rs | 28 +- src/libsyntax/ext/source_util.rs | 2 +- src/libsyntax/ext/tt/macro_parser.rs | 177 +- src/libsyntax/ext/tt/macro_rules.rs | 620 +- src/libsyntax/ext/tt/quoted.rs | 336 +- src/libsyntax/ext/tt/transcribe.rs | 31 +- src/libsyntax/feature_gate.rs | 239 +- src/libsyntax/json.rs | 6 +- src/libsyntax/lib.rs | 27 +- src/libsyntax/mut_visit.rs | 141 +- src/libsyntax/parse/attr.rs | 37 +- src/libsyntax/parse/classify.rs | 2 - src/libsyntax/parse/diagnostics.rs | 793 +- src/libsyntax/parse/lexer/mod.rs | 657 +- src/libsyntax/parse/lexer/tokentrees.rs | 45 +- src/libsyntax/parse/literal.rs | 667 +- src/libsyntax/parse/mod.rs | 162 +- src/libsyntax/parse/parser.rs | 2409 +-- src/libsyntax/parse/token.rs | 369 +- src/libsyntax/parse/unescape.rs | 91 +- .../parse/unescape_error_reporting.rs | 10 + src/libsyntax/print/pp.rs | 2 +- src/libsyntax/print/pprust.rs | 233 +- src/libsyntax/ptr.rs | 14 +- src/libsyntax/source_map.rs | 57 +- src/libsyntax/std_inject.rs | 45 +- src/libsyntax/test.rs | 44 +- src/libsyntax/test_snippet.rs | 4 +- src/libsyntax/tokenstream.rs | 166 +- src/libsyntax/util/lev_distance.rs | 4 +- src/libsyntax/util/node_count.rs | 4 +- src/libsyntax/util/parser.rs | 95 +- src/libsyntax/visit.rs | 60 +- src/libsyntax_ext/asm.rs | 19 +- src/libsyntax_ext/assert.rs | 26 +- src/libsyntax_ext/cfg.rs | 9 +- src/libsyntax_ext/concat.rs | 4 +- src/libsyntax_ext/concat_idents.rs | 8 +- src/libsyntax_ext/deriving/bounds.rs | 8 - src/libsyntax_ext/deriving/clone.rs | 11 +- src/libsyntax_ext/deriving/cmp/eq.rs | 10 +- src/libsyntax_ext/deriving/cmp/ord.rs | 12 +- src/libsyntax_ext/deriving/cmp/partial_eq.rs | 8 +- src/libsyntax_ext/deriving/cmp/partial_ord.rs | 39 +- src/libsyntax_ext/deriving/custom.rs | 8 +- src/libsyntax_ext/deriving/debug.rs | 6 +- src/libsyntax_ext/deriving/default.rs | 7 +- src/libsyntax_ext/deriving/generic/mod.rs | 29 +- src/libsyntax_ext/deriving/generic/ty.rs | 5 +- src/libsyntax_ext/deriving/hash.rs | 7 +- src/libsyntax_ext/deriving/mod.rs | 66 +- src/libsyntax_ext/env.rs | 8 +- src/libsyntax_ext/format.rs | 67 +- src/libsyntax_ext/format_foreign.rs | 249 +- .../format_foreign/printf/tests.rs | 151 + .../format_foreign/shell/tests.rs | 59 + src/libsyntax_ext/global_asm.rs | 2 +- src/libsyntax_ext/lib.rs | 80 +- src/libsyntax_ext/proc_macro_decls.rs | 37 +- src/libsyntax_ext/proc_macro_server.rs | 129 +- src/libsyntax_ext/test.rs | 30 +- src/libsyntax_ext/test_case.rs | 24 +- src/libsyntax_ext/trace_macros.rs | 8 +- src/libsyntax_pos/edition.rs | 5 + src/libsyntax_pos/hygiene.rs | 505 +- src/libsyntax_pos/lib.rs | 77 +- src/libsyntax_pos/symbol.rs | 306 +- src/libterm/lib.rs | 3 - src/libtest/lib.rs | 464 +- src/libtest/stats.rs | 577 +- src/libtest/stats/tests.rs | 574 + src/libtest/tests.rs | 453 + src/libunwind/Cargo.toml | 1 + src/libunwind/lib.rs | 5 +- src/libunwind/libunwind.rs | 9 +- src/libunwind/macros.rs | 35 - src/stage0.txt | 6 +- src/test/assembly/nvptx-arch-default.rs | 1 + src/test/assembly/nvptx-arch-emit-asm.rs | 1 + src/test/assembly/nvptx-arch-link-arg.rs | 1 + src/test/assembly/nvptx-arch-target-cpu.rs | 1 + src/test/assembly/nvptx-atomics.rs | 1 + src/test/assembly/nvptx-internalizing.rs | 1 + src/test/assembly/nvptx-linking-binary.rs | 1 + src/test/assembly/nvptx-linking-cdylib.rs | 1 + src/test/assembly/nvptx-safe-naming.rs | 1 + src/test/auxiliary/rust_test_helpers.c | 40 +- src/test/codegen/align-enum.rs | 1 - src/test/codegen/c-variadic-copy.rs | 16 + src/test/codegen/c-variadic-opt.rs | 15 +- src/test/codegen/c-variadic.rs | 2 +- src/test/codegen/drop.rs | 21 +- src/test/codegen/external-no-mangle-fns.rs | 4 +- .../codegen/external-no-mangle-statics.rs | 4 +- src/test/codegen/function-arguments.rs | 4 +- src/test/codegen/internalize-closures.rs | 6 +- .../codegen/{ => intrinsics}/exact_div.rs | 4 +- src/test/codegen/{ => intrinsics}/likely.rs | 0 .../codegen/{ => intrinsics}/move-val-init.rs | 0 .../codegen/{ => intrinsics}/nontemporal.rs | 0 src/test/codegen/{ => intrinsics}/prefetch.rs | 0 src/test/codegen/intrinsics/unchecked_math.rs | 46 + src/test/codegen/link-dead-code.rs | 12 +- .../local-generics-in-exe-internalized.rs | 4 +- src/test/codegen/match.rs | 4 +- src/test/codegen/pgo-instrumentation.rs | 13 +- .../codegen/repr-transparent-aggregates-1.rs | 59 +- .../codegen/repr-transparent-aggregates-2.rs | 58 +- .../codegen/repr-transparent-aggregates-3.rs | 58 +- src/test/codegen/repr-transparent.rs | 43 +- src/test/codegen/slice-iter-len-eq-zero.rs | 14 + src/test/codegen/target-cpu-on-functions.rs | 4 +- src/test/compile-fail/const-fn-error.rs | 1 + src/test/compile-fail/issue-23595-1.rs | 2 +- src/test/compile-fail/issue-43733-2.rs | 6 +- src/test/compile-fail/issue-52443.rs | 1 + src/test/debuginfo/issue-13213.rs | 1 + src/test/debuginfo/pretty-std.rs | 53 +- src/test/debuginfo/should-fail.rs | 7 + .../incremental/cyclic-trait-hierarchy.rs | 1 - ...ssue-59523-on-implemented-is-not-unused.rs | 2 +- ...layout-scalar-valid-range-is-not-unused.rs | 2 +- src/test/incremental/issue-61530.rs | 17 + src/test/incremental/no_mangle.rs | 4 +- src/test/mir-opt/box_expr.rs | 10 +- src/test/mir-opt/byte_slice.rs | 15 + .../const_prop/const_prop_fails_gracefully.rs | 5 +- src/test/mir-opt/const_prop/indirect.rs | 23 + src/test/mir-opt/const_prop/ref_deref.rs | 21 + src/test/mir-opt/const_prop/reify_fn_ptr.rs | 25 + src/test/mir-opt/const_prop/slice_len.rs | 40 +- src/test/mir-opt/const_prop/switch_int.rs | 8 +- src/test/mir-opt/copy_propagation_arg.rs | 2 + src/test/mir-opt/deaggregator_test_enum_2.rs | 26 +- src/test/mir-opt/generator-drop-cleanup.rs | 3 + .../mir-opt/generator-storage-dead-unwind.rs | 112 + src/test/mir-opt/inline-trait-method.rs | 2 +- src/test/mir-opt/inline-trait-method_2.rs | 2 +- src/test/mir-opt/issue-38669.rs | 17 +- src/test/mir-opt/issue-41110.rs | 9 +- src/test/mir-opt/issue-49232.rs | 57 +- src/test/mir-opt/loop_test.rs | 14 +- src/test/mir-opt/match-arm-scopes.rs | 227 + src/test/mir-opt/match_false_edges.rs | 190 +- src/test/mir-opt/match_test.rs | 60 +- .../mir-opt/nll/region-subtyping-basic.rs | 6 +- .../mir-opt/packed-struct-drop-aligned.rs | 4 +- src/test/mir-opt/remove_fake_borrows.rs | 74 +- src/test/mir-opt/simple-match.rs | 39 + src/test/mir-opt/simplify_if.rs | 4 +- src/test/mir-opt/simplify_match.rs | 4 +- .../mir-opt/storage_live_dead_in_statics.rs | 2 +- src/test/mir-opt/storage_ranges.rs | 2 + src/test/mir-opt/unusual-item-types.rs | 6 +- src/test/mir-opt/while-storage.rs | 59 + src/test/pretty/attr-fn-inner.rs | 11 +- src/test/pretty/attr-literals.rs | 11 +- src/test/pretty/stmt_expr_attributes.rs | 279 +- .../termination-trait-for-box-dyn-error.rs | 2 +- ...mination-trait-for-result-box-error_err.rs | 2 +- .../a-b-a-linker-guard/Makefile | 9 +- .../alloc-extern-crates/fakealloc.rs | 6 +- .../c-link-to-rust-va-list-fn/checkrust.rs | 2 +- .../cross-lang-lto-pgo-smoketest/Makefile | 87 + .../cross-lang-lto-pgo-smoketest/clib.c | 9 + .../cross-lang-lto-pgo-smoketest/cmain.c | 12 + .../cross-lang-lto-pgo-smoketest/main.rs | 11 + .../cross-lang-lto-pgo-smoketest/rustlib.rs | 12 + .../hotplug_codegen_backend/the_backend.rs | 6 +- .../libtest-json/output.json | 2 +- .../run-make-fulldeps/pgo-gen-lto/Makefile | 12 +- .../pgo-gen-no-imp-symbols/Makefile | 12 +- src/test/run-make-fulldeps/pgo-gen/Makefile | 12 +- src/test/run-make-fulldeps/pgo-use/Makefile | 6 +- .../print-target-list/Makefile | 9 +- .../stable-symbol-names/Makefile | 7 +- .../symbol-visibility/Makefile | 21 +- .../run-pass-fulldeps/ast_stmt_expr_attr.rs | 2 +- .../auxiliary/custom-derive-partial-eq.rs | 71 - .../auxiliary/custom-derive-plugin-attr.rs | 84 - .../auxiliary/custom-derive-plugin.rs | 76 - .../auxiliary/issue-40001-plugin.rs | 4 +- .../auxiliary/plugin-args.rs | 20 +- .../auxiliary/roman-numerals.rs | 20 +- .../custom-derive-partial-eq.rs | 10 - .../run-pass-fulldeps/derive-totalsum-attr.rs | 64 - src/test/run-pass-fulldeps/derive-totalsum.rs | 49 - src/test/run-pass-fulldeps/issue-40663.rs | 13 - .../mod_dir_path_canonicalized.rs | 2 +- src/test/run-pass-fulldeps/myriad-closures.rs | 6 +- .../pprust-expr-roundtrip.rs | 91 +- src/test/run-pass/abi-sysv64-arg-passing.rs | 36 + .../issues/issue-62350-sysv-neg-reg-counts.rs | 46 + src/test/run-pass/alignment-gep-tup-like-1.rs | 4 +- .../associated-const-range-match-patterns.rs | 14 + ...ciated-types-doubleendediterator-object.rs | 2 +- .../associated-types-eq-obj.rs | 2 +- ...ociated-types-projection-in-object-type.rs | 6 +- .../async-await/async-fn-size-moved-locals.rs | 98 + .../run-pass/async-await/async-fn-size.rs | 106 + src/test/run-pass/async-await/issue-60709.rs | 28 + src/test/run-pass/attr-before-view-item.rs | 11 - src/test/run-pass/attr-before-view-item2.rs | 13 - src/test/run-pass/attr-mix-new.rs | 14 - .../autoderef-method-on-trait.rs | 2 +- .../run-pass/auxiliary/allocator-dummy.rs | 59 - src/test/run-pass/backtrace.rs | 17 +- src/test/run-pass/binding/pat-ranges.rs | 6 + .../borrowck/borrowck-trait-lifetime.rs | 4 +- .../borrowck/issue-62007-assign-box.rs | 27 + .../borrowck/issue-62007-assign-field.rs | 26 + .../run-pass/cast-rfc0401-vtable-kinds.rs | 10 +- src/test/run-pass/cast-rfc0401.rs | 4 +- src/test/run-pass/cast.rs | 2 +- .../check-static-recursion-foreign.rs | 2 +- src/test/run-pass/cleanup-shortcircuit.rs | 2 +- .../close-over-big-then-small-data.rs | 4 +- src/test/run-pass/codegen-object-shim.rs | 2 +- .../run-pass/coerce/coerce-expect-unsized.rs | 18 +- src/test/run-pass/compiletest-skip-codegen.rs | 7 - src/test/run-pass/const-int-rotate.rs | 11 - src/test/run-pass/const-int-sign.rs | 11 - .../run-pass/{ctfe => consts}/assoc-const.rs | 0 .../run-pass/{ctfe => consts}/bswap-const.rs | 0 .../chained-constants-stackoverflow.rs | 0 .../const-block-non-item-statement-3.rs | 0 .../const-block-non-item-statement.rs | 0 src/test/run-pass/consts/const-block.rs | 4 +- src/test/run-pass/consts/const-endianess.rs | 2 +- src/test/run-pass/consts/const-enum-cast.rs | 13 +- .../run-pass/consts/const-fn-type-name.rs | 37 + .../{ => consts}/const-int-conversion.rs | 20 +- .../{ => consts}/const-int-overflowing.rs | 28 +- src/test/run-pass/consts/const-int-rotate.rs | 41 + .../const-int-saturating-arith.rs | 0 src/test/run-pass/consts/const-int-sign.rs | 21 + .../{ => consts}/const-int-wrapping.rs | 28 +- .../run-pass/{ => consts}/const-needs_drop.rs | 0 src/test/run-pass/consts/const-ptr-nonnull.rs | 14 +- src/test/run-pass/consts/const-ptr-unique.rs | 13 +- .../run-pass/consts/const-trait-to-trait.rs | 8 +- .../{ctfe => consts}/deref_in_pattern.rs | 0 .../run-pass/{ctfe => consts}/ice-48279.rs | 0 .../run-pass/{ctfe => consts}/issue-37550.rs | 0 .../{ctfe => consts}/issue-broken-mir.rs | 0 .../{ctfe => consts}/locals-in-const-fn.rs | 0 .../match-const-fn-structs.rs | 0 .../run-pass/{ctfe => consts}/mozjs-error.rs | 0 .../{ctfe => consts}/non-scalar-cast.rs | 0 .../run-pass/{ctfe => consts}/promotion.rs | 0 .../run-pass/{ctfe => consts}/references.rs | 0 .../run-pass/{ctfe => consts}/repeat_match.rs | 0 .../{ctfe => consts}/return-in-const-fn.rs | 0 .../{ctfe => consts}/signed_enum_discr.rs | 0 .../{ctfe => consts}/transmute-const.rs | 0 .../tuple-struct-constructors.rs | 0 src/test/run-pass/deriving/deriving-show.rs | 2 +- .../run-pass/drop/drop-struct-as-object.rs | 2 +- src/test/run-pass/drop/dynamic-drop.rs | 92 +- .../dst-coerce-custom.rs | 2 +- .../dynamically-sized-types/dst-coerce-rc.rs | 8 +- .../dynamically-sized-types/dst-coercions.rs | 12 +- .../dst-field-align.rs | 8 +- .../dynamically-sized-types/dst-index.rs | 6 +- .../dynamically-sized-types/dst-raw.rs | 12 +- .../dst-trait-tuple.rs | 22 +- .../dynamically-sized-types/dst-trait.rs | 22 +- .../extern/extern-types-trait-impl.rs | 2 +- src/test/run-pass/fat-ptr-cast.rs | 2 +- .../closure-expected-type/issue-38714.rs | 2 +- .../run-pass/generator/addassign-yield.rs | 34 + .../run-pass/generator/drop-and-replace.rs | 44 + src/test/run-pass/generator/overlap-locals.rs | 27 + .../run-pass/generator/size-moved-locals.rs | 62 + src/test/run-pass/generics/generic-object.rs | 2 +- src/test/run-pass/hashmap-memory.rs | 2 +- .../hrtb-binder-levels-in-object-types.rs | 2 +- .../hrtb-debruijn-object-types-in-closures.rs | 2 +- .../hrtb-fn-like-trait-object.rs | 2 +- .../higher-rank-trait-bounds/hrtb-parse.rs | 4 +- .../hrtb-precedence-of-plus.rs | 2 +- .../hrtb-resolve-lifetime.rs | 2 +- .../hrtb-trait-object-paren-notation.rs | 2 +- .../hrtb-trait-object-passed-to-closure.rs | 2 +- src/test/run-pass/ifmt.rs | 2 +- .../run-pass/impl-trait/example-calendar.rs | 4 + src/test/run-pass/inc-range-pat.rs | 2 + src/test/run-pass/issues/issue-10802.rs | 8 +- src/test/run-pass/issues/issue-11205.rs | 36 +- src/test/run-pass/issues/issue-11267.rs | 2 +- src/test/run-pass/issues/issue-11677.rs | 4 +- src/test/run-pass/issues/issue-11709.rs | 2 +- src/test/run-pass/issues/issue-12744.rs | 2 +- .../issues/issue-13259-windows-tcb-trash.rs | 4 +- src/test/run-pass/issues/issue-13507-2.rs | 2 +- src/test/run-pass/issues/issue-13808.rs | 2 +- src/test/run-pass/issues/issue-14399.rs | 2 +- src/test/run-pass/issues/issue-14589.rs | 6 +- src/test/run-pass/issues/issue-14821.rs | 8 +- src/test/run-pass/issues/issue-14919.rs | 2 +- src/test/run-pass/issues/issue-14958.rs | 12 +- src/test/run-pass/issues/issue-15155.rs | 8 +- src/test/run-pass/issues/issue-15763.rs | 8 +- .../issue-15881-model-lexer-dotdotdot.rs | 1 + src/test/run-pass/issues/issue-16739.rs | 6 +- src/test/run-pass/issues/issue-16922.rs | 2 +- src/test/run-pass/issues/issue-17322.rs | 4 +- src/test/run-pass/issues/issue-17351.rs | 2 +- src/test/run-pass/issues/issue-17771.rs | 6 +- src/test/run-pass/issues/issue-17897.rs | 2 +- src/test/run-pass/issues/issue-19001.rs | 2 +- .../run-pass/issues/issue-20055-box-trait.rs | 2 +- src/test/run-pass/issues/issue-20575.rs | 2 +- src/test/run-pass/issues/issue-20676.rs | 2 +- src/test/run-pass/issues/issue-20953.rs | 4 +- src/test/run-pass/issues/issue-21058.rs | 67 +- src/test/run-pass/issues/issue-21361.rs | 4 +- src/test/run-pass/issues/issue-21655.rs | 2 +- src/test/run-pass/issues/issue-2190-1.rs | 4 +- src/test/run-pass/issues/issue-22346.rs | 2 +- src/test/run-pass/issues/issue-2288.rs | 4 +- src/test/run-pass/issues/issue-23261.rs | 4 +- src/test/run-pass/issues/issue-23485.rs | 2 +- src/test/run-pass/issues/issue-24010.rs | 2 +- src/test/run-pass/issues/issue-24086.rs | 4 +- src/test/run-pass/issues/issue-25339.rs | 2 +- src/test/run-pass/issues/issue-25515.rs | 2 +- .../issues/issue-25549-multiple-drop.rs | 2 +- src/test/run-pass/issues/issue-25700-2.rs | 2 +- src/test/run-pass/issues/issue-25757.rs | 2 +- src/test/run-pass/issues/issue-26641.rs | 2 +- src/test/run-pass/issues/issue-26709.rs | 2 +- src/test/run-pass/issues/issue-26802.rs | 2 +- src/test/run-pass/issues/issue-26805.rs | 2 +- src/test/run-pass/issues/issue-26905.rs | 2 +- src/test/run-pass/issues/issue-27268.rs | 2 +- src/test/run-pass/issues/issue-2734.rs | 4 +- src/test/run-pass/issues/issue-2735.rs | 4 +- src/test/run-pass/issues/issue-27890.rs | 4 +- src/test/run-pass/issues/issue-2935.rs | 2 +- src/test/run-pass/issues/issue-3052.rs | 2 +- src/test/run-pass/issues/issue-30530.rs | 8 +- src/test/run-pass/issues/issue-30615.rs | 2 +- src/test/run-pass/issues/issue-32389.rs | 2 +- src/test/run-pass/issues/issue-33387.rs | 8 +- src/test/run-pass/issues/issue-33461.rs | 2 +- src/test/run-pass/issues/issue-34503.rs | 2 +- src/test/run-pass/issues/issue-35815.rs | 2 +- src/test/run-pass/issues/issue-36260.rs | 2 +- .../issues/issue-36786-resolve-call.rs | 2 +- src/test/run-pass/issues/issue-3702.rs | 2 +- src/test/run-pass/issues/issue-3794.rs | 4 +- src/test/run-pass/issues/issue-39292.rs | 2 +- src/test/run-pass/issues/issue-39367.rs | 6 +- src/test/run-pass/issues/issue-39823.rs | 8 +- src/test/run-pass/issues/issue-41053.rs | 4 +- src/test/run-pass/issues/issue-41744.rs | 2 +- src/test/run-pass/issues/issue-42210.rs | 4 +- src/test/run-pass/issues/issue-43132.rs | 2 +- src/test/run-pass/issues/issue-4333.rs | 2 +- src/test/run-pass/issues/issue-46069.rs | 2 +- src/test/run-pass/issues/issue-47638.rs | 4 +- ...e-5008-borrowed-traitobject-method-call.rs | 4 +- src/test/run-pass/issues/issue-5192.rs | 6 +- src/test/run-pass/issues/issue-5666.rs | 2 +- src/test/run-pass/issues/issue-5708.rs | 10 +- src/test/run-pass/issues/issue-5988.rs | 2 +- src/test/run-pass/issues/issue-6128.rs | 2 +- src/test/run-pass/issues/issue-6157.rs | 4 +- src/test/run-pass/issues/issue-61894.rs | 19 + src/test/run-pass/issues/issue-6318.rs | 4 +- src/test/run-pass/issues/issue-7563.rs | 2 +- src/test/run-pass/issues/issue-7911.rs | 12 +- src/test/run-pass/issues/issue-8248.rs | 4 +- src/test/run-pass/issues/issue-8249.rs | 4 +- src/test/run-pass/issues/issue-9129.rs | 4 +- .../issue-9394-inherited-trait-calls.rs | 2 +- src/test/run-pass/issues/issue-9951.rs | 10 +- src/test/run-pass/last-use-in-cap-clause.rs | 2 +- ...line-endings-string-literal-doc-comment.rs | 3 + .../run-pass/macros/colorful-write-macros.rs | 4 +- .../macros/macro-at-most-once-rep-2015.rs | 50 + .../macros/macro-at-most-once-rep-2018.rs | 50 + .../run-pass/macros/macro-at-most-once-rep.rs | 33 - src/test/run-pass/macros/macro-attributes.rs | 1 - .../run-pass/macros/type-macros-simple.rs | 2 +- ...thod-argument-inference-associated-type.rs | 4 +- .../run-pass/methods/method-attributes.rs | 31 - .../mir/mir_build_match_comparisons.rs | 2 +- src/test/run-pass/mir/mir_codegen_calls.rs | 8 +- .../run-pass/mir/mir_codegen_critical_edge.rs | 2 +- src/test/run-pass/mir/mir_coercions.rs | 10 +- src/test/run-pass/mir/mir_raw_fat_ptr.rs | 6 +- src/test/run-pass/multi-panic.rs | 2 +- src/test/run-pass/new-box.rs | 6 +- src/test/run-pass/newlambdas-ret-infer.rs | 2 +- src/test/run-pass/newlambdas-ret-infer2.rs | 2 +- ...ject-lifetime-default-default-to-static.rs | 12 +- .../object-lifetime-default-from-rptr-box.rs | 10 +- .../object-lifetime-default-from-rptr-mut.rs | 12 +- .../object-lifetime-default-from-rptr.rs | 16 +- src/test/run-pass/object-method-numbering.rs | 2 +- .../objects-coerce-freeze-borrored.rs | 6 +- ...owned-object-borrowed-method-headerless.rs | 8 +- .../objects-owned-object-owned-method.rs | 2 +- .../overloaded-calls-object-one-arg.rs | 2 +- .../overloaded-calls-object-two-args.rs | 2 +- .../overloaded-calls-object-zero-args.rs | 2 +- .../panics/panic-handler-flail-wildly.rs | 2 + src/test/run-pass/panics/panic-safe.rs | 2 +- src/test/run-pass/privacy/privacy-ns.rs | 12 +- src/test/run-pass/raw-fat-ptr.rs | 4 +- .../regions-bound-lists-feature-gate.rs | 2 +- ...-close-over-type-parameter-successfully.rs | 4 +- .../run-pass/regions/regions-copy-closure.rs | 4 +- .../regions/regions-debruijn-of-object.rs | 4 +- .../regions-early-bound-trait-param.rs | 18 +- .../regions/regions-fn-subtyping-2.rs | 4 +- .../run-pass/regions/regions-fn-subtyping.rs | 8 +- ...regions-infer-region-in-fn-but-not-type.rs | 2 +- .../regions-lifetime-nonfree-late-bound.rs | 8 +- .../regions/regions-lub-ref-ref-rc.rs | 8 +- ...ions-on-closures-to-inference-variables.rs | 2 +- .../regions/regions-static-closure.rs | 4 +- .../regions/regions-trait-object-1.rs | 4 +- .../rfcs/rfc-1789-as-cell/from-mut.rs | 1 - src/test/run-pass/string-box-error.rs | 8 +- src/test/run-pass/struct-ctor-mangling.rs | 12 + src/test/run-pass/structs-enums/align-enum.rs | 1 - .../structs-enums/class-attributes-1.rs | 21 - .../structs-enums/class-attributes-2.rs | 33 - .../class-cast-to-trait-cross-crate-2.rs | 4 +- .../class-cast-to-trait-multiple-types.rs | 2 +- .../structs-enums/class-cast-to-trait.rs | 2 +- .../structs-enums/class-separate-impl.rs | 4 +- .../structs-enums/enum-null-pointer-opt.rs | 20 +- ...object-lifetime-default-from-ref-struct.rs | 22 +- ...bject-lifetime-default-from-rptr-struct.rs | 10 +- src/test/run-pass/traits/auto-traits.rs | 2 +- .../traits/impl-inherent-prefer-over-trait.rs | 4 +- .../infer-from-object-trait-issue-26952.rs | 2 +- .../traits/kindck-owned-trait-contains-1.rs | 4 +- .../traits/object-one-type-two-traits.rs | 10 +- .../traits/parameterized-trait-with-bounds.rs | 10 +- .../run-pass/traits/trait-bounds-basic.rs | 8 +- .../run-pass/traits/trait-bounds-in-arc.rs | 22 +- .../trait-bounds-on-structs-and-enums.rs | 4 +- .../run-pass/traits/trait-coercion-generic.rs | 4 +- src/test/run-pass/traits/trait-coercion.rs | 6 +- src/test/run-pass/traits/trait-impl-2.rs | 2 +- src/test/run-pass/traits/trait-impl.rs | 6 +- ...ritance-cast-without-call-to-supertrait.rs | 4 +- .../run-pass/traits/trait-inheritance-cast.rs | 4 +- .../traits/trait-object-auto-dedup.rs | 9 +- .../run-pass/traits/trait-object-exclusion.rs | 2 +- .../run-pass/traits/trait-object-generics.rs | 4 +- .../traits/trait-object-lifetime-first.rs | 4 +- .../trait-object-with-lifetime-bound.rs | 4 +- .../traits/trait-region-pointer-simple.rs | 2 +- .../traits-impl-object-overlap-issue-23853.rs | 2 +- .../run-pass/traits/traits-issue-26339.rs | 2 +- .../traits/traits-repeated-supertrait.rs | 2 +- src/test/run-pass/traits/ufcs-trait-object.rs | 2 +- src/test/run-pass/trivial_casts.rs | 14 +- src/test/run-pass/tydesc-name.rs | 2 +- .../run-pass/type-alias-enum-variants-2.rs | 30 - src/test/run-pass/type-alias-enum-variants.rs | 30 - src/test/run-pass/type-id-higher-rank-2.rs | 6 +- src/test/run-pass/type-id-higher-rank.rs | 18 +- .../run-pass/type-infer-generalize-ty-var.rs | 8 +- .../unboxed-closures-blanket-fn-mut.rs | 2 +- .../unboxed-closures-blanket-fn.rs | 2 +- .../unboxed-closures-boxed.rs | 4 +- ...ed-closures-call-sugar-object-autoderef.rs | 2 +- .../unboxed-closures-call-sugar-object.rs | 2 +- .../unboxed-closures-extern-fn-hr.rs | 2 +- ...fer-arg-types-from-expected-object-type.rs | 2 +- .../unboxed-closures-infer-recursive-fn.rs | 8 +- .../unboxed-closures-manual-impl.rs | 2 +- .../unboxed-closures-monomorphization.rs | 2 +- .../unboxed-closures-prelude.rs | 4 +- .../unboxed-closures-sugar-object.rs | 2 +- .../run-pass/unique/unique-object-move.rs | 2 +- .../run-pass/unsized-locals/fnbox-compat.rs | 12 - src/test/run-pass/unsized2.rs | 16 +- src/test/run-pass/variadic-ffi.rs | 45 + src/test/run-pass/weird-exprs.rs | 18 + .../wf-bound-region-in-object-type.rs | 2 +- .../rustdoc-ui/failed-doctest-compile-fail.rs | 11 + .../failed-doctest-compile-fail.stdout | 14 + .../failed-doctest-missing-codes.rs | 11 + .../failed-doctest-missing-codes.stdout | 26 + src/test/rustdoc-ui/failed-doctest-output.rs | 5 +- .../rustdoc-ui/failed-doctest-output.stdout | 30 +- .../rustdoc-ui/failed-doctest-should-panic.rs | 11 + .../failed-doctest-should-panic.stdout | 14 + .../rustdoc-ui/unparseable-doc-test.stdout | 4 +- src/test/rustdoc/const-generics/add-impl.rs | 21 + .../const-generics/const-generic-slice.rs | 12 + .../const-impl.rs} | 5 +- src/test/rustdoc/deep-structures.rs | 104 + src/test/rustdoc/empty-section.rs | 3 + src/test/rustdoc/issue-50159.rs | 2 +- src/test/rustdoc/issue-60726.rs | 35 + src/test/rustdoc/synthetic_auto/basic.rs | 2 +- .../rustdoc/synthetic_auto/crate-local.rs | 9 + src/test/rustdoc/synthetic_auto/manual.rs | 2 +- src/test/rustdoc/trait-attributes.rs | 6 +- .../internal-lints/pass_ty_by_ref.rs | 30 +- .../internal-lints/pass_ty_by_ref.stderr | 42 +- .../internal-lints/qualified_ty_ty_ctxt.rs | 8 +- .../qualified_ty_ty_ctxt.stderr | 6 +- src/test/ui/access-mode-in-closures.stderr | 17 +- src/test/ui/annotate-snippet/missing-type.rs | 5 + .../ui/annotate-snippet/missing-type.stderr | 6 + src/test/ui/anon-params-denied-2018.rs | 8 +- src/test/ui/anon-params-denied-2018.stderr | 58 +- .../ui/anonymous-higher-ranked-lifetime.rs | 8 +- .../anonymous-higher-ranked-lifetime.stderr | 32 +- src/test/ui/array-break-length.rs | 2 + src/test/ui/array-break-length.stderr | 25 +- src/test/ui/asm/asm-misplaced-option.rs | 6 +- src/test/ui/asm/asm-misplaced-option.stderr | 4 +- .../associated-const-in-trait.rs | 2 +- .../associated-const-in-trait.stderr | 4 +- .../auxiliary/fn-aux.rs | 177 + .../auxiliary/fn-dyn-aux.rs | 182 + .../bad-bounds-on-assoc-in-trait.rs | 60 + .../bad-bounds-on-assoc-in-trait.stderr | 85 + .../bounds-on-assoc-in-trait.rs | 51 + .../ui/associated-type-bounds/duplicate.rs | 161 + .../associated-type-bounds/duplicate.stderr | 632 + .../dyn-existential-type.rs | 67 + .../ui/associated-type-bounds/dyn-lcsit.rs | 69 + .../associated-type-bounds/dyn-lcsit.stderr | 6 + .../dyn-rpit-and-let.rs | 73 + .../entails-sized-object-safety.rs | 26 + .../ui/associated-type-bounds/enum-bounds.rs | 122 + .../existential-type.rs | 67 + src/test/ui/associated-type-bounds/fn-apit.rs | 58 + src/test/ui/associated-type-bounds/fn-aux.rs | 12 + .../ui/associated-type-bounds/fn-dyn-apit.rs | 60 + .../ui/associated-type-bounds/fn-inline.rs | 62 + .../ui/associated-type-bounds/fn-where.rs | 78 + .../ui/associated-type-bounds/fn-wrap-apit.rs | 64 + .../implied-region-constraints.nll.stderr | 24 + .../implied-region-constraints.rs | 47 + .../implied-region-constraints.stderr | 20 + .../ui/associated-type-bounds/inside-adt.rs | 36 + .../associated-type-bounds/inside-adt.stderr | 79 + src/test/ui/associated-type-bounds/lcsit.rs | 78 + .../ui/associated-type-bounds/lcsit.stderr | 6 + src/test/ui/associated-type-bounds/rpit.rs | 64 + .../associated-type-bounds/struct-bounds.rs | 115 + .../ui/associated-type-bounds/trait-params.rs | 116 + .../ui/associated-type-bounds/type-alias.rs | 19 + .../associated-type-bounds/type-alias.stderr | 97 + .../ui/associated-type-bounds/union-bounds.rs | 123 + ...pe-projection-from-multiple-supertraits.rs | 2 +- ...rojection-from-multiple-supertraits.stderr | 10 +- .../associated-types/associated-types-eq-3.rs | 2 +- .../associated-types-incomplete-object.rs | 8 +- .../associated-types-incomplete-object.stderr | 12 +- .../associated-types-overridden-binding-2.rs | 2 +- ...sociated-types-overridden-binding-2.stderr | 8 +- .../associated-types-overridden-binding.rs | 2 +- ...associated-types-overridden-binding.stderr | 1 + .../associated-types-unconstrained.stderr | 1 + .../bound-lifetime-constrained.object.stderr | 12 +- .../bound-lifetime-constrained.rs | 4 +- ...ound-lifetime-in-binding-only.angle.stderr | 6 +- ...ound-lifetime-in-binding-only.paren.stderr | 6 +- .../bound-lifetime-in-binding-only.rs | 4 +- .../bound-lifetime-in-return-only.rs | 4 +- .../ui/associated-types/cache/chrono-scan.rs | 17 +- src/test/ui/associated-types/cache/elision.rs | 5 +- .../async-await}/async-await.rs | 17 +- src/test/ui/async-await/async-fn-nonsend.rs | 59 + .../ui/async-await/async-fn-nonsend.stderr | 87 + .../async-fn-path-elision.rs | 0 .../async-fn-path-elision.stderr | 0 .../async-await/async-fn-send-uses-nonsend.rs | 59 + .../{ => async-await}/async-matches-expr.rs | 0 .../{ => async-await}/async-with-closure.rs | 2 +- ...015-edition-error-in-non-macro-position.rs | 0 ...edition-error-in-non-macro-position.stderr | 0 .../await-keyword/2015-edition-warning.fixed | 0 .../await-keyword/2015-edition-warning.rs | 0 .../await-keyword/2015-edition-warning.stderr | 0 ...018-edition-error-in-non-macro-position.rs | 0 ...edition-error-in-non-macro-position.stderr | 0 .../await-keyword/2018-edition-error.rs | 0 .../await-keyword/2018-edition-error.stderr | 0 .../incorrect-syntax-suggestions.rs | 0 .../incorrect-syntax-suggestions.stderr | 0 .../await-keyword/post_expansion_error.rs | 0 .../await-keyword/post_expansion_error.stderr | 0 .../async-await}/await-macro.rs | 4 +- .../async-await/dont-print-desugared-async.rs | 9 + .../dont-print-desugared-async.stderr | 12 + .../async-await/dont-suggest-missing-await.rs | 21 + .../dont-suggest-missing-await.stderr | 12 + .../drop-order/auxiliary/arc_wake.rs | 64 + ...-for-async-fn-parameters-by-ref-binding.rs | 0 .../drop-order-for-async-fn-parameters.rs | 0 .../drop-order-locals-are-hidden.rs | 0 .../drop-order-locals-are-hidden.stderr | 0 .../edition-deny-async-fns-2015.rs | 6 + .../edition-deny-async-fns-2015.stderr | 28 +- .../ui/async-await/generics-and-bounds.rs | 90 + src/test/ui/async-await/issue-61452.rs | 14 + src/test/ui/async-await/issue-61452.stderr | 23 + src/test/ui/async-await/issue-61793.rs | 19 + .../{ => issues}/auxiliary/issue-60674.rs | 0 .../{ => async-await}/issues/issue-51719.rs | 3 +- .../issues/issue-51719.stderr | 4 +- .../{ => async-await}/issues/issue-51751.rs | 0 .../issues/issue-51751.stderr | 0 .../{ => async-await/issues}/issue-53249.rs | 2 +- .../issues}/issue-54752-async-block.rs | 6 +- .../{ => async-await}/issues/issue-54974.rs | 2 +- .../{ => async-await}/issues/issue-55324.rs | 0 .../async-await/issues}/issue-55809.rs | 0 .../{ => async-await}/issues/issue-58885.rs | 0 .../{ => async-await}/issues/issue-59001.rs | 0 .../async-await/issues}/issue-59972.rs | 2 + .../async-await/{ => issues}/issue-60518.rs | 0 .../issues}/issue-60655-latebound-regions.rs | 0 .../async-await/{ => issues}/issue-60674.rs | 0 .../{ => issues}/issue-60674.stdout | 0 src/test/ui/async-await/issues/issue-61187.rs | 9 + .../ui/async-await/issues/issue-61187.stderr | 11 + src/test/ui/async-await/issues/issue-61986.rs | 21 + src/test/ui/async-await/issues/issue-62009.rs | 19 + .../ui/async-await/issues/issue-62009.stderr | 49 + .../async-await/multiple-lifetimes/elided.rs | 12 + .../async-await/multiple-lifetimes/fn-ptr.rs | 14 + .../ui/async-await/multiple-lifetimes/hrtb.rs | 17 + .../async-await/multiple-lifetimes/named.rs | 12 + .../multiple-lifetimes/partial-relation.rs | 15 + .../multiple-lifetimes/ret-impl-trait-fg.rs | 18 + .../ret-impl-trait-no-fg.rs | 18 + .../ret-impl-trait-no-fg.stderr | 10 + .../ret-impl-trait-one.nll.stderr | 15 + .../multiple-lifetimes/ret-impl-trait-one.rs | 27 + .../ret-impl-trait-one.stderr | 11 + .../async-await/multiple-lifetimes/ret-ref.rs | 46 + .../multiple-lifetimes/ret-ref.stderr | 37 + .../multiple-lifetimes/variance.rs | 18 + .../no-args-non-move-async-closure.rs | 0 .../no-args-non-move-async-closure.stderr | 0 src/test/ui/async-await/no-async-const.rs | 8 + src/test/ui/async-await/no-async-const.stderr | 8 + src/test/ui/async-await/no-const-async.rs | 9 + src/test/ui/async-await/no-const-async.stderr | 18 + src/test/ui/async-await/no-unsafe-async.rs | 11 + .../ui/async-await/no-unsafe-async.stderr | 14 + .../recursive-async-impl-trait-type.rs | 0 .../recursive-async-impl-trait-type.stderr | 0 .../async-await/suggest-missing-await.fixed | 32 + .../ui/async-await/suggest-missing-await.rs | 32 + .../async-await/suggest-missing-await.stderr | 27 + .../unresolved_type_param.rs | 4 +- .../unresolved_type_param.stderr | 4 +- src/test/ui/async-fn-multiple-lifetimes.rs | 19 - .../ui/async-fn-multiple-lifetimes.stderr | 20 - src/test/ui/attr-eq-token-tree.rs | 2 - src/test/ui/attr-eq-token-tree.stderr | 2 +- src/test/ui/attr-usage-repr.rs | 3 +- src/test/ui/attr-usage-repr.stderr | 12 +- .../ui/attributes/attr-before-view-item.rs | 10 + .../ui/attributes/attr-before-view-item2.rs | 12 + src/test/ui/attributes/attr-mix-new.rs | 11 + .../attrs-with-no-formal-in-generics-1.rs | 0 .../attrs-with-no-formal-in-generics-1.stderr | 0 .../attrs-with-no-formal-in-generics-2.rs | 0 .../attrs-with-no-formal-in-generics-2.stderr | 0 .../attrs-with-no-formal-in-generics-3.rs | 0 .../attrs-with-no-formal-in-generics-3.stderr | 0 src/test/ui/attributes/class-attributes-1.rs | 19 + src/test/ui/attributes/class-attributes-2.rs | 31 + .../attributes}/item-attributes.rs | 117 +- src/test/ui/attributes/method-attributes.rs | 28 + src/test/ui/attributes/obsolete-attr.rs | 7 + src/test/ui/attributes/obsolete-attr.stderr | 21 + src/test/ui/attributes/unknown-attr.rs | 9 + src/test/ui/attributes/unknown-attr.stderr | 30 + .../attributes}/variant-attributes.rs | 23 +- src/test/ui/bad/bad-lint-cap3.rs | 5 +- src/test/ui/bad/bad-lint-cap3.stderr | 2 +- src/test/ui/bad/bad-sized.rs | 2 +- src/test/ui/bad/bad-sized.stderr | 21 +- src/test/ui/binop/binop-move-semantics.rs | 4 +- src/test/ui/binop/binop-move-semantics.stderr | 8 +- .../borrowck-anon-fields-variant.stderr | 1 + .../borrowck-borrow-mut-object-twice.rs | 2 +- .../borrowck-closures-use-after-free.stderr | 2 +- .../borrowck/borrowck-consume-upcast-box.rs | 4 +- .../borrowck-consume-upcast-box.stderr | 2 +- .../borrowck/borrowck-describe-lvalue.stderr | 2 + .../borrowck-escaping-closure-error-2.rs | 2 +- ...ature-nll-overrides-migrate.edition.stderr | 12 +- .../borrowck-feature-nll-overrides-migrate.rs | 4 +- ...feature-nll-overrides-migrate.zflag.stderr | 12 +- .../ui/borrowck/borrowck-fn-in-const-a.rs | 2 +- .../ui/borrowck/borrowck-fn-in-const-a.stderr | 4 +- ...ck-for-loop-correct-cmt-for-pattern.stderr | 33 +- src/test/ui/borrowck/borrowck-in-static.rs | 4 +- .../ui/borrowck/borrowck-in-static.stderr | 4 +- .../ui/borrowck/borrowck-issue-2657-2.stderr | 6 +- .../borrowck-migrate-to-nll.edition.stderr | 12 +- .../borrowck-migrate-to-nll.zflag.stderr | 12 +- .../borrowck/borrowck-move-by-capture.stderr | 8 +- .../borrowck/borrowck-move-error-with-note.rs | 3 - .../borrowck-move-error-with-note.stderr | 35 +- .../borrowck/borrowck-move-from-unsafe-ptr.rs | 2 +- .../borrowck-move-from-unsafe-ptr.stderr | 6 +- .../borrowck-move-in-irrefut-pat.stderr | 31 +- ...k-move-out-of-overloaded-auto-deref.stderr | 2 +- ...rrowck-move-out-of-overloaded-deref.stderr | 4 +- .../borrowck-move-out-of-static-item.rs | 2 +- .../borrowck-move-out-of-static-item.stderr | 4 +- ...rrowck-move-out-of-struct-with-dtor.stderr | 25 +- ...-move-out-of-tuple-struct-with-dtor.stderr | 25 +- .../borrowck-mut-borrow-linear-errors.stderr | 14 +- .../borrowck/borrowck-mutate-in-guard.stderr | 2 + .../ui/borrowck/borrowck-object-lifetime.rs | 8 +- ...borrowck-overloaded-index-move-from-vec.rs | 2 +- ...owck-overloaded-index-move-from-vec.stderr | 4 +- .../borrowck-struct-update-with-dtor.stderr | 10 +- ...orrowck-use-uninitialized-in-cast-trait.rs | 2 +- ...wck-use-uninitialized-in-cast-trait.stderr | 2 +- .../borrowck/borrowck-vec-pattern-nesting.rs | 3 + .../borrowck-vec-pattern-nesting.stderr | 35 +- .../issue-47215-ice-from-drop-elab.rs | 2 +- .../issue-47215-ice-from-drop-elab.stderr | 4 +- src/test/ui/borrowck/issue-51415.stderr | 14 +- ...54597-reject-move-out-of-borrow-via-pat.rs | 2 +- ...7-reject-move-out-of-borrow-via-pat.stderr | 6 +- ...e-in-static-initializer-issue-38520.stderr | 8 +- ...regions-bound-missing-bound-in-impl.stderr | 4 +- .../regions-escape-unboxed-closure.rs | 2 +- .../return-local-binding-from-desugaring.rs | 33 + ...eturn-local-binding-from-desugaring.stderr | 12 + .../two-phase-nonrecv-autoref.nll.stderr | 2 +- .../ui/borrowck/two-phase-nonrecv-autoref.rs | 6 +- ...es-move-upvar-from-non-once-ref-closure.rs | 2 +- ...ove-upvar-from-non-once-ref-closure.stderr | 4 +- src/test/ui/bounds-lifetime.rs | 2 +- src/test/ui/bounds-lifetime.stderr | 6 +- src/test/ui/by-move-pattern-binding.stderr | 11 +- src/test/ui/c-variadic/variadic-ffi-1.stderr | 4 +- .../ui/c-variadic/variadic-ffi-4.nll.stderr | 52 +- src/test/ui/c-variadic/variadic-ffi-4.rs | 16 +- src/test/ui/c-variadic/variadic-ffi-4.stderr | 81 +- src/test/ui/{cast_char.rs => cast-char.rs} | 0 .../ui/{cast_char.stderr => cast-char.stderr} | 6 +- ...cast-to-unsized-trait-object-suggestion.rs | 4 +- ...-to-unsized-trait-object-suggestion.stderr | 12 +- src/test/ui/casts-differing-anon.rs | 2 +- src/test/ui/casts-issue-46365.rs | 2 +- .../ui/check-static-values-constraints.stderr | 4 +- src/test/ui/class-cast-to-trait.rs | 2 +- .../ui/closure_context/issue-26046-fn-mut.rs | 2 +- .../ui/closure_context/issue-26046-fn-once.rs | 2 +- .../ui/closures/closure-array-break-length.rs | 2 + .../closure-array-break-length.stderr | 25 +- .../closure-immutable-outer-variable.fixed | 2 +- .../closure-immutable-outer-variable.rs | 2 +- ...herence-overlapping-inherent-impl-trait.rs | 4 +- ...nce-overlapping-inherent-impl-trait.stderr | 11 +- .../overlapping_inherent_impls.stderr | 1 + src/test/ui/codemap_tests/two_files_data.rs | 2 +- .../coerce-expect-unsized-ascribed.rs | 16 +- .../coerce-expect-unsized-ascribed.stderr | 14 +- ...mpl-trait-for-trait-object-safe.old.stderr | 2 +- ...impl-trait-for-trait-object-safe.re.stderr | 2 +- ...erence-impl-trait-for-trait-object-safe.rs | 2 +- .../coherence-impl-trait-for-trait.old.stderr | 12 +- .../coherence-impl-trait-for-trait.re.stderr | 12 +- .../coherence-impl-trait-for-trait.rs | 8 +- ...nce-overlap-downstream-inherent.old.stderr | 1 + ...ence-overlap-downstream-inherent.re.stderr | 1 + ...ce-overlap-issue-23516-inherent.old.stderr | 1 + ...nce-overlap-issue-23516-inherent.re.stderr | 1 + ...rence-overlap-upstream-inherent.old.stderr | 1 + ...erence-overlap-upstream-inherent.re.stderr | 1 + .../coherence-projection-ok-orphan.rs | 10 +- .../ui/coherence/coherence-projection-ok.rs | 5 +- ...ce_copy_like_err_fundamental_struct_ref.rs | 5 +- src/test/ui/coherence/coherence_local.rs | 7 +- src/test/ui/coherence/coherence_local_ref.rs | 5 +- .../cfg-attr-empty-is-unused.rs | 13 + .../cfg-attr-empty-is-unused.stderr | 21 + .../cfg-generic-params.rs | 38 + .../cfg-generic-params.stderr | 66 + .../conditional-compilation/cfg_attr_path.rs | 7 +- .../ui/confuse-field-and-method/issue-2392.rs | 12 +- .../issue-2392.stderr | 28 +- .../confuse-field-and-method/issue-32128.rs | 2 +- .../const-generics/apit-with-const-param.rs | 10 + .../apit-with-const-param.stderr | 6 + .../array-wrapper-struct-ctor.rs | 15 + .../array-wrapper-struct-ctor.stderr | 6 + src/test/ui/const-generics/broken-mir-1.rs | 17 + .../ui/const-generics/broken-mir-1.stderr | 6 + src/test/ui/const-generics/broken-mir-2.rs | 9 + .../ui/const-generics/broken-mir-2.stderr | 19 + .../cannot-infer-const-args.stderr | 2 +- .../cannot-infer-type-for-const-param.rs | 6 +- .../cannot-infer-type-for-const-param.stderr | 11 +- .../condition-in-trait-const-arg.rs | 12 + .../condition-in-trait-const-arg.stderr | 6 + .../const-generic-array-wrapper.rs | 18 + .../const-generic-array-wrapper.stderr | 6 + .../derive-debug-array-wrapper.rs | 9 + .../derive-debug-array-wrapper.stderr | 19 + .../fn-taking-const-generic-array.rs | 16 + .../fn-taking-const-generic-array.stderr | 6 + .../issue-60818-struct-constructors.rs | 10 + .../issue-60818-struct-constructors.stderr | 6 + src/test/ui/const-generics/issue-61336-1.rs | 12 + .../ui/const-generics/issue-61336-1.stderr | 14 + src/test/ui/const-generics/issue-61336-2.rs | 16 + .../ui/const-generics/issue-61336-2.stderr | 18 + src/test/ui/const-generics/issue-61336.rs | 16 + src/test/ui/const-generics/issue-61336.stderr | 18 + src/test/ui/const-generics/issue-61422.rs | 15 + src/test/ui/const-generics/issue-61422.stderr | 6 + .../mut-ref-const-param-array.rs | 19 + .../mut-ref-const-param-array.stderr | 6 + .../transparent-maybeunit-array-wrapper.rs | 11 + ...transparent-maybeunit-array-wrapper.stderr | 6 + .../uninferred-consts-during-codegen-1.rs | 18 + .../uninferred-consts-during-codegen-1.stderr | 6 + .../uninferred-consts-during-codegen-2.rs | 18 + .../uninferred-consts-during-codegen-2.stderr | 6 + src/test/ui/consts/array-literal-index-oob.rs | 1 + .../ui/consts/array-literal-index-oob.stderr | 8 +- src/test/ui/consts/const-array-oob-arith.rs | 8 +- .../ui/consts/const-array-oob-arith.stderr | 6 +- .../ui/consts/const-eval/const_transmute.rs | 3 +- src/test/ui/consts/const-eval/enum_discr.rs | 1 - .../const-eval/ice-generic-assoc-const.rs | 2 +- src/test/ui/consts/const-eval/issue-53401.rs | 2 +- .../consts/const-eval/match-test-ptr-null.rs | 1 + .../const-eval/match-test-ptr-null.stderr | 12 +- .../ui/consts/const-eval/promoted_errors.rs | 24 +- .../consts/const-eval/promoted_errors.stderr | 48 +- src/test/ui/consts/const-eval/ub-upvars.rs | 2 +- .../ui/consts/const-eval/ub-upvars.stderr | 2 +- .../ui/consts/const-eval/union-ub-fat-ptr.rs | 10 +- .../consts/const-eval/union-ub-fat-ptr.stderr | 16 +- .../ui/consts/const-fn-stability-calls-3.rs | 5 +- src/test/ui/consts/const-int-conversion.rs | 2 - .../ui/consts/const-int-conversion.stderr | 14 +- src/test/ui/consts/const-match-pattern-arm.rs | 2 + .../ui/consts/const-match-pattern-arm.stderr | 18 +- src/test/ui/consts/const-size_of-cycle.stderr | 2 +- src/test/ui/consts/const-unsized.rs | 4 +- src/test/ui/consts/const-unsized.stderr | 8 +- src/test/ui/consts/const_arg_promotable2.rs | 18 + .../ui/consts/const_arg_promotable2.stderr | 8 + .../const_constructor/const-construct-call.rs | 116 + ...ure-gate-const_constructor.const_fn.stderr | 34 + ...gate-const_constructor.min_const_fn.stderr | 34 + .../feature-gate-const_constructor.rs | 28 + .../ui/consts/const_let_refutable.nll.stderr | 2 +- src/test/ui/consts/const_let_refutable.stderr | 4 +- src/test/ui/consts/const_short_circuit.rs | 2 - src/test/ui/consts/const_short_circuit.stderr | 8 +- src/test/ui/consts/enum-discr-type-err.rs | 29 + src/test/ui/consts/enum-discr-type-err.stderr | 19 + src/test/ui/consts/issue-62045.rs | 5 + .../min_const_fn/min_const_fn.nll.stderr | 12 +- .../ui/consts/min_const_fn/min_const_fn.rs | 12 +- .../consts/min_const_fn/min_const_fn.stderr | 13 +- .../min_const_fn/min_const_fn_dyn.stderr | 1 + .../min_const_fn/min_const_fn_libstd.rs | 2 - .../min_const_fn/min_const_fn_unsafe.rs | 4 +- .../miri_unleashed/mutable_references.rs | 35 + .../miri_unleashed/mutable_references.stderr | 26 + .../miri_unleashed/mutable_references_ice.rs | 29 + .../mutable_references_ice.stderr | 21 + src/test/ui/consts/packed_pattern.rs | 19 + src/test/ui/consts/packed_pattern2.rs | 27 + .../ui/consts/single_variant_match_ice.rs | 11 +- .../ui/consts/single_variant_match_ice.stderr | 20 +- src/test/ui/consts/static-cycle-error.rs | 11 + .../ui/consts/static-raw-pointer-interning.rs | 15 + .../consts/static-raw-pointer-interning2.rs | 15 + .../ui/{ => consts}/underscore_const_names.rs | 5 +- .../consts/uninhabited-const-issue-61744.rs | 19 + .../uninhabited-const-issue-61744.stderr | 24 + src/test/ui/consts/union_constant.rs | 1 + src/test/ui/cross/cross-borrow-trait.rs | 8 +- src/test/ui/cross/cross-borrow-trait.stderr | 12 +- src/test/ui/custom-attribute-multisegment.rs | 2 - .../ui/custom-attribute-multisegment.stderr | 2 +- src/test/ui/custom-derive/auxiliary/plugin.rs | 28 - src/test/ui/custom-derive/derive-in-mod.rs | 13 - .../helper-attr-blocked-by-import-ambig.rs | 12 - ...helper-attr-blocked-by-import-ambig.stderr | 21 - .../helper-attr-blocked-by-import.rs | 28 - src/test/ui/custom-derive/issue-36935.rs | 12 - src/test/ui/custom-derive/issue-36935.stderr | 10 - src/test/ui/custom-test-frameworks-simple.rs | 2 +- .../cycle-projection-based-on-where-clause.rs | 1 - ...le-projection-based-on-where-clause.stderr | 11 +- .../cycle-trait-default-type-trait.rs | 2 +- .../cycle-trait-default-type-trait.stderr | 10 +- .../deprecated_no_stack_check.stderr | 2 +- .../deprecation/deprecation-in-staged-api.rs | 4 +- .../deprecation-in-staged-api.stderr | 2 +- src/test/ui/deprecation/invalid-literal.rs | 2 +- .../ui/deprecation/invalid-literal.stderr | 10 +- src/test/ui/derived-errors/issue-31997.rs | 2 +- src/test/ui/derived-errors/issue-31997.stderr | 2 +- src/test/ui/derives/deriving-bounds.rs | 4 +- src/test/ui/derives/deriving-bounds.stderr | 16 +- .../derives/deriving-meta-empty-trait-list.rs | 6 +- .../deriving-meta-empty-trait-list.stderr | 11 +- src/test/ui/destructure-trait-ref.rs | 19 +- src/test/ui/destructure-trait-ref.stderr | 18 +- src/test/ui/did_you_mean/E0178.rs | 2 + src/test/ui/did_you_mean/E0178.stderr | 8 +- src/test/ui/did_you_mean/bad-assoc-ty.rs | 2 +- src/test/ui/did_you_mean/bad-assoc-ty.stderr | 8 +- src/test/ui/did_you_mean/issue-40006.rs | 2 +- src/test/ui/did_you_mean/issue-40006.stderr | 10 +- ...ect-reference-without-parens-suggestion.rs | 2 + ...reference-without-parens-suggestion.stderr | 6 +- ...constructing-destructing-struct-let.stderr | 7 +- ...nstructing-destructing-struct-match.stderr | 11 +- .../dropck_no_diverge_on_nonregular_1.stderr | 4 +- .../dropck_no_diverge_on_nonregular_2.stderr | 4 +- .../dropck_no_diverge_on_nonregular_3.stderr | 6 +- .../ui/dropck/dropck_trait_cycle_checked.rs | 16 +- .../dropck/dropck_trait_cycle_checked.stderr | 24 +- src/test/ui/dst/dst-bad-assign-2.rs | 4 +- src/test/ui/dst/dst-bad-assign-3.rs | 4 +- src/test/ui/dst/dst-bad-assign.rs | 4 +- src/test/ui/dst/dst-bad-coerce1.rs | 4 +- src/test/ui/dst/dst-bad-coerce1.stderr | 12 +- src/test/ui/dst/dst-bad-coerce2.rs | 4 +- src/test/ui/dst/dst-bad-coerce2.stderr | 12 +- src/test/ui/dst/dst-bad-coerce3.rs | 4 +- src/test/ui/dst/dst-bad-coerce3.stderr | 8 +- src/test/ui/dst/dst-bad-coercions.rs | 8 +- src/test/ui/dst/dst-bad-coercions.stderr | 36 +- src/test/ui/dst/dst-index.rs | 8 +- src/test/ui/dst/dst-index.stderr | 8 +- .../ui/dst/dst-object-from-unsized-type.rs | 8 +- .../dst/dst-object-from-unsized-type.stderr | 24 +- src/test/ui/dst/dst-rvalue.rs | 2 +- src/test/ui/dst/dst-rvalue.stderr | 9 +- .../ui/elide-errors-on-mismatched-tuple.rs | 2 +- .../ui/emit-artifact-notifications.nll.stderr | 2 +- src/test/ui/emit-artifact-notifications.rs | 2 + .../ui/emit-artifact-notifications.stderr | 2 +- src/test/ui/empty/empty-never-array.stderr | 1 + .../arbitrary_enum_discriminant-no-repr.rs | 9 + ...arbitrary_enum_discriminant-no-repr.stderr | 14 + .../arbitrary_enum_discriminant.rs | 56 + .../discriminant_value-wrapper.rs | 1 + .../enum-discriminant}/discriminant_value.rs | 18 +- ...eature-gate-arbitrary_enum_discriminant.rs | 10 + ...re-gate-arbitrary_enum_discriminant.stderr | 36 + src/test/ui/error-codes/E0033-teach.rs | 2 +- src/test/ui/error-codes/E0033-teach.stderr | 10 +- src/test/ui/error-codes/E0033.rs | 2 +- src/test/ui/error-codes/E0033.stderr | 10 +- src/test/ui/error-codes/E0038.rs | 2 +- src/test/ui/error-codes/E0038.stderr | 4 +- src/test/ui/error-codes/E0049.rs | 10 + src/test/ui/error-codes/E0049.stderr | 19 +- src/test/ui/error-codes/E0120.rs | 2 +- src/test/ui/error-codes/E0120.stderr | 4 +- src/test/ui/error-codes/E0191.rs | 2 +- src/test/ui/error-codes/E0191.stderr | 4 +- src/test/ui/error-codes/E0220.rs | 4 +- src/test/ui/error-codes/E0220.stderr | 10 +- src/test/ui/error-codes/E0225.rs | 8 +- src/test/ui/error-codes/E0225.stderr | 27 +- src/test/ui/error-codes/E0275.stderr | 68 +- src/test/ui/error-codes/E0393.rs | 2 +- src/test/ui/error-codes/E0393.stderr | 6 +- src/test/ui/error-codes/E0452.stderr | 4 +- src/test/ui/error-codes/E0478.rs | 2 +- src/test/ui/error-codes/E0478.stderr | 4 +- src/test/ui/{ => error-codes}/E0501.rs | 0 src/test/ui/{ => error-codes}/E0501.stderr | 0 src/test/ui/{ => error-codes}/E0506.rs | 0 src/test/ui/{ => error-codes}/E0506.stderr | 0 src/test/ui/error-codes/E0507.stderr | 4 +- src/test/ui/{ => error-codes}/E0508-fail.rs | 0 .../ui/{ => error-codes}/E0508-fail.stderr | 1 + src/test/ui/{ => error-codes}/E0508.rs | 0 src/test/ui/{ => error-codes}/E0508.stderr | 1 + src/test/ui/error-codes/E0509.stderr | 1 + src/test/ui/error-codes/E0517.stderr | 8 +- src/test/ui/{ => error-codes}/E0583.rs | 0 src/test/ui/{ => error-codes}/E0583.stderr | 0 src/test/ui/{ => error-codes}/E0594.rs | 0 src/test/ui/{ => error-codes}/E0594.stderr | 0 src/test/ui/{ => error-codes}/E0596.rs | 0 src/test/ui/{ => error-codes}/E0596.stderr | 0 src/test/ui/error-codes/E0605.rs | 2 +- src/test/ui/error-codes/E0607.rs | 2 +- src/test/ui/error-codes/E0617.rs | 4 +- src/test/ui/error-codes/E0617.stderr | 8 +- src/test/ui/{ => error-codes}/E0642.rs | 0 src/test/ui/{ => error-codes}/E0642.stderr | 0 src/test/ui/error-codes/E0646.stderr | 4 +- src/test/ui/error-codes/E0647.stderr | 4 +- src/test/ui/{ => error-codes}/E0660.rs | 0 src/test/ui/{ => error-codes}/E0660.stderr | 0 src/test/ui/{ => error-codes}/E0661.rs | 0 src/test/ui/{ => error-codes}/E0661.stderr | 0 src/test/ui/{ => error-codes}/E0662.rs | 0 src/test/ui/{ => error-codes}/E0662.stderr | 0 src/test/ui/{ => error-codes}/E0663.rs | 0 src/test/ui/{ => error-codes}/E0663.stderr | 0 src/test/ui/{ => error-codes}/E0664.rs | 0 src/test/ui/{ => error-codes}/E0664.stderr | 0 src/test/ui/{ => error-codes}/E0665.rs | 0 src/test/ui/{ => error-codes}/E0665.stderr | 0 src/test/ui/{ => error-codes}/E0705.rs | 0 src/test/ui/{ => error-codes}/E0705.stderr | 0 src/test/ui/error-codes/E0719.rs | 4 +- src/test/ui/error-codes/E0719.stderr | 10 +- src/test/ui/error-codes/E0730.rs | 11 + src/test/ui/error-codes/E0730.stderr | 15 + .../e0119/auxiliary/complex_impl_support.rs | 0 .../e0119/auxiliary/issue-23563-a.rs | 0 .../{ => error-codes}/e0119/complex-impl.rs | 0 .../e0119/complex-impl.stderr | 0 .../e0119/conflict-with-std.rs | 0 .../e0119/conflict-with-std.stderr | 0 .../ui/{ => error-codes}/e0119/issue-23563.rs | 0 .../e0119/issue-23563.stderr | 0 .../ui/{ => error-codes}/e0119/issue-27403.rs | 0 .../e0119/issue-27403.stderr | 0 .../ui/{ => error-codes}/e0119/issue-28981.rs | 0 .../e0119/issue-28981.stderr | 0 .../ui/{ => error-codes}/e0119/so-37347311.rs | 0 .../e0119/so-37347311.stderr | 0 src/test/ui/error-festival.rs | 2 +- .../no_revealing_outside_defining_module.rs | 2 +- src/test/ui/expanded-cfg.rs | 6 +- src/test/ui/explain.stdout | 2 +- src/test/ui/extenv/issue-55897.rs | 5 + src/test/ui/extenv/issue-55897.stderr | 8 +- src/test/ui/extern/extern-const.fixed | 2 +- src/test/ui/extern/extern-const.rs | 2 +- src/test/ui/fat-ptr-cast.rs | 2 +- src/test/ui/fat-ptr-cast.stderr | 6 +- .../issue-43106-gating-of-builtin-attrs.rs | 19 +- ...issue-43106-gating-of-builtin-attrs.stderr | 404 +- .../issue-43106-gating-of-deprecated.rs | 3 +- .../issue-43106-gating-of-macro_use.rs | 2 +- .../issue-43106-gating-of-macro_use.stderr | 8 +- .../feature-gate-associated_type_bounds.rs | 72 + ...feature-gate-associated_type_bounds.stderr | 145 + .../feature-gate-member-constraints.rs | 9 + .../feature-gate-member-constraints.stderr | 10 + .../ui/feature-gates/feature-gate-nll.stderr | 1 + .../feature-gate-repr_align_enum.rs | 10 - .../feature-gate-repr_align_enum.stderr | 12 - .../feature-gate-rustc-attrs-1.rs | 1 + .../feature-gate-rustc-attrs-1.stderr | 11 +- .../feature-gate-transparent_enums.rs | 6 + .../feature-gate-transparent_enums.stderr | 12 + .../feature-gate-transparent_unions.rs | 7 + .../feature-gate-transparent_unions.stderr | 12 + .../feature-gate-trivial_bounds.rs | 4 +- .../feature-gate-trivial_bounds.stderr | 4 +- .../feature-gate-type_alias_enum_variants.rs | 19 - ...ature-gate-type_alias_enum_variants.stderr | 34 - .../feature-gate-underscore_const_names.rs | 14 - ...feature-gate-underscore_const_names.stderr | 18 - .../feature-gate-unsized_locals.rs | 2 +- .../feature-gate-unsized_locals.stderr | 2 +- .../feature-gate-unsized_tuple_coercion.rs | 2 +- ...feature-gate-unsized_tuple_coercion.stderr | 6 +- .../underscore_const_names_feature_gate.rs | 3 - ...underscore_const_names_feature_gate.stderr | 12 - src/test/ui/fmt/format-string-error-2.rs | 1 - src/test/ui/fmt/format-string-error-2.stderr | 36 +- src/test/ui/fn-in-pat.stderr | 4 +- src/test/ui/fn/fn-trait-formatting.rs | 6 +- src/test/ui/fn/fn-trait-formatting.stderr | 12 +- ...unctional-struct-update-noncopyable.stderr | 5 +- src/test/ui/gated-bad-feature.rs | 14 +- src/test/ui/gated-bad-feature.stderr | 32 +- .../issue-61442-stmt-expr-with-drop.rs | 32 + src/test/ui/glob-cycles.rs | 5 +- src/test/ui/higher-lifetime-bounds.rs | 4 +- src/test/ui/higher-lifetime-bounds.stderr | 12 +- src/test/ui/hygiene/assoc_ty_bindings.rs | 5 +- src/test/ui/if/if-loop.rs | 6 +- src/test/ui/impl-trait/hidden-lifetimes.rs | 63 + .../ui/impl-trait/hidden-lifetimes.stderr | 27 + .../ui/impl-trait/impl-trait-plus-priority.rs | 2 +- .../infinite-impl-trait-issue-38064.rs | 0 .../infinite-impl-trait-issue-38064.stderr | 0 ...issue-21659-show-relevant-trait-impls-3.rs | 0 ...e-21659-show-relevant-trait-impls-3.stderr | 0 .../ui/impl-trait/{ => issues}/issue-42479.rs | 0 .../ui/impl-trait/{ => issues}/issue-49376.rs | 0 .../ui/impl-trait/{ => issues}/issue-52128.rs | 0 src/test/ui/impl-trait/issues/issue-53457.rs | 15 + .../issue-55608-captures-empty-region.rs | 0 .../issue-57464-unexpected-regions.rs | 0 ...-deeply-nested-impl-trait-in-assoc-proj.rs | 0 ...ply-nested-impl-trait-in-assoc-proj.stderr | 0 .../issue-57979-impl-trait-in-path.rs | 0 .../issue-57979-impl-trait-in-path.stderr | 0 ...e-57979-nested-impl-trait-in-assoc-proj.rs | 0 ...979-nested-impl-trait-in-assoc-proj.stderr | 0 .../{ => issues}/universal-issue-48703.rs | 0 .../{ => issues}/universal-issue-48703.stderr | 0 ...iversal-turbofish-in-method-issue-50950.rs | 0 ...sal-turbofish-in-method-issue-50950.stderr | 0 src/test/ui/impl-trait/multiple-lifetimes.rs | 12 + .../multiple-lifetimes/error-handling.rs | 22 + .../multiple-lifetimes/error-handling.stderr | 12 + .../multiple-lifetimes/inverse-bounds.rs | 54 + .../multiple-lifetimes/inverse-bounds.stderr | 19 + .../ordinary-bounds-pick-original-elided.rs | 29 + ...dinary-bounds-pick-original-existential.rs | 32 + .../ordinary-bounds-pick-original.rs | 29 + .../ordinary-bounds-pick-other.rs | 46 + .../ordinary-bounds-unrelated.nll.stderr | 9 + .../ordinary-bounds-unrelated.rs | 38 + .../ordinary-bounds-unrelated.stderr | 21 + .../ordinary-bounds-unsuited.nll.stderr | 9 + .../ordinary-bounds-unsuited.rs | 41 + .../ordinary-bounds-unsuited.stderr | 21 + ...t_outlive_least_region_or_bound.nll.stderr | 4 +- .../impl-trait/needs_least_region_or_bound.rs | 16 +- .../needs_least_region_or_bound.stderr | 8 - .../static-return-lifetime-infered.nll.stderr | 4 +- src/test/ui/imports/extern-crate-used.rs | 8 +- src/test/ui/imports/import-crate-var.rs | 4 +- src/test/ui/imports/import-crate-var.stderr | 2 +- ...124-anon-lifetime-in-struct-declaration.rs | 10 + ...anon-lifetime-in-struct-declaration.stderr | 9 + .../mismatched_trait_impl-2.rs | 4 +- .../mismatched_trait_impl-2.stderr | 6 +- .../ui/infinite/infinite-autoderef.stderr | 6 +- .../ui/infinite/infinite-instantiation.stderr | 2 +- .../infinite/infinite-macro-expansion.stderr | 2 +- .../ui/intrinsics/unchecked_math_unsafe.rs | 8 + .../intrinsics/unchecked_math_unsafe.stderr | 27 + .../ui/intrinsics/unchecked_math_unstable.rs | 8 + .../intrinsics/unchecked_math_unstable.stderr | 27 + .../ui/invalid-self-argument/bare-fn-start.rs | 5 +- .../bare-fn-start.stderr | 8 +- src/test/ui/invalid-self-argument/bare-fn.rs | 5 +- .../ui/invalid-self-argument/bare-fn.stderr | 8 +- src/test/ui/invalid-self-argument/trait-fn.rs | 4 +- .../ui/invalid-self-argument/trait-fn.stderr | 4 +- src/test/ui/invalid_crate_type_syntax.rs | 2 +- src/test/ui/invalid_crate_type_syntax.stderr | 4 +- src/test/ui/issue-53912.rs | 37 + .../ui/{ => issues}/auxiliary/issue-59764.rs | 0 src/test/ui/issues/issue-10291.nll.stderr | 2 +- src/test/ui/issues/issue-10291.rs | 2 +- src/test/ui/issues/issue-10291.stderr | 8 +- src/test/ui/issues/issue-10902.rs | 8 +- src/test/ui/issues/issue-11192.stderr | 2 +- src/test/ui/issues/issue-11374.rs | 6 +- src/test/ui/issues/issue-11515.rs | 4 +- src/test/ui/issues/issue-11612.rs | 4 +- src/test/ui/issues/issue-11740.rs | 6 +- src/test/ui/issues/issue-12028.stderr | 1 + src/test/ui/issues/issue-12187-1.rs | 2 +- src/test/ui/issues/issue-12187-1.stderr | 4 +- src/test/ui/issues/issue-12187-2.rs | 2 +- src/test/ui/issues/issue-12187-2.stderr | 4 +- src/test/ui/issues/issue-12470.rs | 4 +- src/test/ui/issues/issue-13033.rs | 4 +- src/test/ui/issues/issue-13033.stderr | 12 +- src/test/ui/issues/issue-13352.rs | 2 +- src/test/ui/issues/issue-13853-2.rs | 2 +- src/test/ui/issues/issue-13853-2.stderr | 6 +- src/test/ui/issues/issue-14285.rs | 4 +- src/test/ui/issues/issue-14285.stderr | 4 +- src/test/ui/issues/issue-14309.stderr | 10 +- src/test/ui/issues/issue-14366.rs | 2 +- src/test/ui/issues/issue-14366.stderr | 2 +- src/test/ui/issues/issue-14901.rs | 4 +- src/test/ui/issues/issue-14959.rs | 12 +- src/test/ui/issues/issue-15381.stderr | 1 + src/test/ui/issues/issue-16098.stderr | 2 +- src/test/ui/issues/issue-16250.stderr | 2 +- src/test/ui/issues/issue-16668.rs | 2 +- src/test/ui/issues/issue-16922.rs | 4 +- src/test/ui/issues/issue-16922.stderr | 4 +- src/test/ui/issues/issue-16994.rs | 7 +- src/test/ui/issues/issue-17441.rs | 4 +- src/test/ui/issues/issue-17441.stderr | 12 +- src/test/ui/issues/issue-17458.rs | 2 +- src/test/ui/issues/issue-17458.stderr | 4 +- src/test/ui/issues/issue-17551.stderr | 4 +- .../ui/issues/issue-17718-static-move.stderr | 4 +- src/test/ui/issues/issue-17959.rs | 2 +- src/test/ui/issues/issue-18107.rs | 2 +- src/test/ui/issues/issue-18107.stderr | 4 +- src/test/ui/issues/issue-18188.rs | 2 +- src/test/ui/issues/issue-18400.stderr | 66 +- src/test/ui/issues/issue-18446-2.rs | 2 +- src/test/ui/issues/issue-18446.rs | 4 +- src/test/ui/issues/issue-18783.rs | 6 +- src/test/ui/issues/issue-18819.rs | 2 +- src/test/ui/issues/issue-18819.stderr | 4 +- src/test/ui/issues/issue-18919.rs | 2 +- src/test/ui/issues/issue-18937.rs | 2 +- src/test/ui/issues/issue-18959.rs | 4 +- src/test/ui/issues/issue-18959.stderr | 4 +- src/test/ui/issues/issue-18988.rs | 2 +- src/test/ui/issues/issue-19380.rs | 2 +- src/test/ui/issues/issue-19380.stderr | 4 +- src/test/ui/issues/issue-19404.rs | 8 +- src/test/ui/issues/issue-19482.rs | 2 +- src/test/ui/issues/issue-19482.stderr | 4 +- src/test/ui/issues/issue-19538.rs | 2 +- src/test/ui/issues/issue-19538.stderr | 10 +- src/test/ui/issues/issue-19601.rs | 9 +- src/test/ui/issues/issue-20261.stderr | 2 +- src/test/ui/issues/issue-20396.rs | 2 +- src/test/ui/issues/issue-20413.stderr | 136 +- src/test/ui/issues/issue-20605.rs | 2 +- src/test/ui/issues/issue-20692.rs | 2 +- src/test/ui/issues/issue-20692.stderr | 4 +- src/test/ui/issues/issue-20772.rs | 1 - src/test/ui/issues/issue-20772.stderr | 13 +- src/test/ui/issues/issue-20801.rs | 12 +- src/test/ui/issues/issue-20801.stderr | 24 +- src/test/ui/issues/issue-20831-debruijn.rs | 6 +- .../ui/issues/issue-20831-debruijn.stderr | 12 +- src/test/ui/issues/issue-20939.rs | 2 +- src/test/ui/issues/issue-20939.stderr | 4 +- src/test/ui/issues/issue-21177.rs | 1 - src/test/ui/issues/issue-21177.stderr | 11 +- src/test/ui/issues/issue-21363.rs | 2 +- src/test/ui/issues/issue-21596.rs | 5 + src/test/ui/issues/issue-21596.stderr | 13 + src/test/ui/issues/issue-21950.rs | 2 +- src/test/ui/issues/issue-21950.stderr | 10 +- src/test/ui/issues/issue-22034.rs | 6 +- src/test/ui/issues/issue-22034.stderr | 2 +- src/test/ui/issues/issue-22289.rs | 2 +- src/test/ui/issues/issue-22289.stderr | 4 +- src/test/ui/issues/issue-22312.rs | 2 +- src/test/ui/issues/issue-22312.stderr | 4 +- src/test/ui/issues/issue-22370.rs | 2 +- src/test/ui/issues/issue-22370.stderr | 6 +- src/test/ui/issues/issue-22434.rs | 2 +- src/test/ui/issues/issue-22434.stderr | 4 +- src/test/ui/issues/issue-22560.rs | 2 +- src/test/ui/issues/issue-22560.stderr | 32 +- src/test/ui/issues/issue-22603.rs | 5 +- src/test/ui/issues/issue-22644.stderr | 2 +- src/test/ui/issues/issue-22781.rs | 2 +- src/test/ui/issues/issue-22789.rs | 5 +- src/test/ui/issues/issue-22814.rs | 2 +- src/test/ui/issues/issue-22872.rs | 2 +- src/test/ui/issues/issue-22872.stderr | 6 +- src/test/ui/issues/issue-22933-1.rs | 8 +- src/test/ui/issues/issue-23024.rs | 4 +- src/test/ui/issues/issue-23024.stderr | 16 +- src/test/ui/issues/issue-23041.rs | 2 +- src/test/ui/issues/issue-23046.rs | 2 +- src/test/ui/issues/issue-23046.stderr | 4 +- src/test/ui/issues/issue-23122-2.stderr | 12 +- src/test/ui/issues/issue-23281.rs | 2 +- src/test/ui/issues/issue-23281.stderr | 4 +- src/test/ui/issues/issue-23302-3.rs | 1 - src/test/ui/issues/issue-23302-3.stderr | 24 +- src/test/ui/issues/issue-24434.rs | 5 +- src/test/ui/issues/issue-24446.rs | 2 +- src/test/ui/issues/issue-24446.stderr | 4 +- src/test/ui/issues/issue-24883.rs | 5 +- src/test/ui/issues/issue-25180.rs | 2 +- src/test/ui/issues/issue-25368.stderr | 4 +- src/test/ui/issues/issue-2590.rs | 2 +- src/test/ui/issues/issue-2590.stderr | 4 +- src/test/ui/issues/issue-26056.rs | 2 +- src/test/ui/issues/issue-26056.stderr | 4 +- src/test/ui/issues/issue-26614.rs | 7 +- src/test/ui/issues/issue-26638.rs | 2 +- src/test/ui/issues/issue-26638.stderr | 6 +- src/test/ui/issues/issue-26905.rs | 2 +- src/test/ui/issues/issue-26930.rs | 6 +- src/test/ui/issues/issue-27105.rs | 2 +- .../issue-27282-move-ref-mut-into-guard.rs | 2 +- ...issue-27282-move-ref-mut-into-guard.stderr | 12 +- src/test/ui/issues/issue-27697.rs | 21 + src/test/ui/issues/issue-28279.rs | 4 +- src/test/ui/issues/issue-28433.rs | 2 - src/test/ui/issues/issue-28433.stderr | 4 +- src/test/ui/issues/issue-28576.rs | 2 +- src/test/ui/issues/issue-28576.stderr | 2 +- src/test/ui/issues/issue-2904.rs | 2 +- src/test/ui/issues/issue-29857.rs | 4 +- src/test/ui/issues/issue-31769.rs | 2 +- src/test/ui/issues/issue-31769.stderr | 4 +- .../ui/issues/issue-31924-non-snake-ffi.rs | 8 +- src/test/ui/issues/issue-32119.rs | 6 +- src/test/ui/issues/issue-32222.rs | 5 +- src/test/ui/issues/issue-32797.rs | 4 +- src/test/ui/issues/issue-32922.rs | 5 +- src/test/ui/issues/issue-32963.rs | 2 +- src/test/ui/issues/issue-32963.stderr | 15 +- src/test/ui/issues/issue-32995.rs | 4 +- src/test/ui/issues/issue-32995.stderr | 12 +- .../issues/issue-33140-traitobject-crate.rs | 158 +- .../issue-33140-traitobject-crate.stderr | 26 +- src/test/ui/issues/issue-33140.rs | 12 +- src/test/ui/issues/issue-33140.stderr | 3 +- src/test/ui/issues/issue-33241.rs | 6 +- src/test/ui/issues/issue-33571.rs | 2 +- src/test/ui/issues/issue-33571.stderr | 8 +- src/test/ui/issues/issue-34028.rs | 4 +- src/test/ui/issues/issue-34171.rs | 4 +- src/test/ui/issues/issue-3424.rs | 2 +- src/test/ui/issues/issue-34255-1.stderr | 2 +- src/test/ui/issues/issue-34418.rs | 5 +- src/test/ui/issues/issue-34839.rs | 5 +- src/test/ui/issues/issue-35139.rs | 6 +- src/test/ui/issues/issue-35546.rs | 4 +- src/test/ui/issues/issue-35570.rs | 6 +- src/test/ui/issues/issue-35976.rs | 4 +- src/test/ui/issues/issue-3609.rs | 2 +- src/test/ui/issues/issue-36116.rs | 6 +- src/test/ui/issues/issue-36379.rs | 6 +- src/test/ui/issues/issue-36638.rs | 2 - src/test/ui/issues/issue-36638.stderr | 6 +- src/test/ui/issues/issue-36708.stderr | 4 +- src/test/ui/issues/issue-36839.rs | 6 +- src/test/ui/issues/issue-3702-2.rs | 4 +- src/test/ui/issues/issue-37051.rs | 10 +- src/test/ui/issues/issue-37366.rs | 8 +- src/test/ui/issues/issue-37510.rs | 4 +- src/test/ui/issues/issue-37515.rs | 10 +- src/test/ui/issues/issue-37515.stderr | 4 +- src/test/ui/issues/issue-38160.rs | 7 +- src/test/ui/issues/issue-38381.rs | 4 +- src/test/ui/issues/issue-38404.rs | 2 +- src/test/ui/issues/issue-38404.stderr | 4 +- src/test/ui/issues/issue-38591.rs | 10 + src/test/ui/issues/issue-38604.rs | 2 +- src/test/ui/issues/issue-38604.stderr | 4 +- src/test/ui/issues/issue-39388.rs | 2 +- src/test/ui/issues/issue-39388.stderr | 2 +- src/test/ui/issues/issue-40000.rs | 4 +- src/test/ui/issues/issue-40350.rs | 5 +- .../issue-40402-ref-hints/issue-40402-1.rs | 2 +- .../issue-40402-1.stderr | 4 +- .../issue-40402-ref-hints/issue-40402-2.rs | 2 +- .../issue-40402-2.stderr | 8 +- .../ui/issues/issue-40510-1.migrate.stderr | 1 + .../ui/issues/issue-40510-3.migrate.stderr | 1 + src/test/ui/issues/issue-41139.rs | 4 +- src/test/ui/issues/issue-41139.stderr | 6 +- src/test/ui/issues/issue-42312.rs | 2 +- src/test/ui/issues/issue-42312.stderr | 6 +- src/test/ui/issues/issue-4335.rs | 2 +- src/test/ui/issues/issue-4335.stderr | 6 +- src/test/ui/issues/issue-43733.rs | 8 +- src/test/ui/issues/issue-43733.stderr | 12 +- src/test/ui/issues/issue-43988.rs | 4 +- src/test/ui/issues/issue-43988.stderr | 16 +- ...96-scribble-on-boxed-borrow.migrate.stderr | 3 + src/test/ui/issues/issue-45730.rs | 2 +- src/test/ui/issues/issue-46843.rs | 4 +- src/test/ui/issues/issue-46843.stderr | 10 +- src/test/ui/issues/issue-4736.stderr | 7 +- src/test/ui/issues/issue-4972.rs | 4 +- src/test/ui/issues/issue-49824.stderr | 1 + src/test/ui/issues/issue-50714-1.stderr | 4 +- src/test/ui/issues/issue-50714.stderr | 4 +- src/test/ui/issues/issue-50761.rs | 2 +- src/test/ui/issues/issue-50781.rs | 2 +- src/test/ui/issues/issue-51279.rs | 27 - src/test/ui/issues/issue-51279.stderr | 60 - src/test/ui/issues/issue-51301.rs | 35 + src/test/ui/issues/issue-51301.stderr | 12 + src/test/ui/issues/issue-5153.rs | 2 +- src/test/ui/issues/issue-5153.stderr | 6 +- src/test/ui/issues/issue-5216.rs | 4 +- src/test/ui/issues/issue-53419.rs | 2 +- src/test/ui/issues/issue-54189.rs | 6 + src/test/ui/issues/issue-54189.stderr | 9 + src/test/ui/issues/issue-54582.rs | 2 +- src/test/ui/issues/issue-55587.stderr | 4 +- src/test/ui/issues/issue-55796.rs | 4 +- src/test/ui/issues/issue-5883.rs | 4 +- src/test/ui/issues/issue-5883.stderr | 2 +- src/test/ui/{ => issues}/issue-59508-1.rs | 0 src/test/ui/{ => issues}/issue-59508-1.stderr | 0 src/test/ui/{ => issues}/issue-59508.fixed | 0 src/test/ui/{ => issues}/issue-59508.rs | 0 src/test/ui/{ => issues}/issue-59508.stderr | 0 src/test/ui/{ => issues}/issue-59756.fixed | 0 src/test/ui/{ => issues}/issue-59756.rs | 0 src/test/ui/{ => issues}/issue-59756.stderr | 0 src/test/ui/{ => issues}/issue-59764.rs | 0 src/test/ui/{ => issues}/issue-59764.stderr | 0 src/test/ui/{ => issues}/issue-60075.rs | 0 src/test/ui/{ => issues}/issue-60075.stderr | 0 src/test/ui/{ => issues}/issue-60622.rs | 0 src/test/ui/{ => issues}/issue-60622.stderr | 0 src/test/ui/issues/issue-60989.rs | 2 +- src/test/ui/issues/issue-60989.stderr | 4 +- src/test/ui/issues/issue-61106.rs | 6 + src/test/ui/issues/issue-61106.stderr | 15 + src/test/ui/issues/issue-61108.rs | 7 + src/test/ui/issues/issue-61108.stderr | 17 + src/test/ui/issues/issue-61858.rs | 3 + src/test/ui/issues/issue-61858.stderr | 10 + src/test/ui/issues/issue-7013.rs | 4 +- src/test/ui/issues/issue-7013.stderr | 2 +- ...7673-cast-generically-implemented-trait.rs | 4 +- src/test/ui/issues/issue-7813.stderr | 4 +- src/test/ui/issues/issue-8398.rs | 2 +- src/test/ui/issues/issue-8727.stderr | 2 +- src/test/ui/issues/issue-9719.rs | 12 +- .../type-arg-mismatch-due-to-impl-trait.rs | 1 + ...type-arg-mismatch-due-to-impl-trait.stderr | 9 +- src/test/ui/kindck/kindck-copy.rs | 12 +- src/test/ui/kindck/kindck-copy.stderr | 12 +- .../kindck/kindck-impl-type-params.nll.stderr | 24 +- src/test/ui/kindck/kindck-impl-type-params.rs | 10 +- .../ui/kindck/kindck-impl-type-params.stderr | 26 +- .../ui/kindck/kindck-inherited-copy-bound.rs | 2 +- .../kindck/kindck-inherited-copy-bound.stderr | 6 +- src/test/ui/kindck/kindck-send-object.rs | 8 +- src/test/ui/kindck/kindck-send-object.stderr | 8 +- .../ui/kindck/kindck-send-object1.nll.stderr | 8 +- src/test/ui/kindck/kindck-send-object1.rs | 10 +- src/test/ui/kindck/kindck-send-object1.stderr | 12 +- src/test/ui/kindck/kindck-send-object2.rs | 8 +- src/test/ui/kindck/kindck-send-object2.stderr | 8 +- .../ui/lifetime_starts_expressions.stderr | 2 +- ...etime-bound-will-change-warning.nll.stderr | 4 +- .../lifetime-bound-will-change-warning.rs | 16 +- .../lifetime-bound-will-change-warning.stderr | 4 +- .../lifetime-elision-return-type-trait.rs | 2 +- .../lifetime-elision-return-type-trait.stderr | 4 +- ...non-regions-using-trait-objects.nll.stderr | 12 +- ...3-both-anon-regions-using-trait-objects.rs | 2 +- ...th-anon-regions-using-trait-objects.stderr | 4 +- .../liveness-assign-imm-local-notes.stderr | 6 +- .../auxiliary/def_colliding_external.rs | 7 + .../auxiliary/def_illtyped_external.rs | 5 + ...-detect-extern-generated-name-collision.rs | 21 + ...ect-extern-generated-name-collision.stderr | 8 + ...e-detect-local-generated-name-collision.rs | 23 + ...tect-local-generated-name-collision.stderr | 8 + .../linkage-attr/linkage-requires-raw-ptr.rs | 10 + .../linkage-requires-raw-ptr.stderr | 8 + src/test/ui/{ => linkage-attr}/linkage2.rs | 2 +- .../ui/{ => linkage-attr}/linkage2.stderr | 2 +- src/test/ui/{ => linkage-attr}/linkage3.rs | 0 .../ui/{ => linkage-attr}/linkage3.stderr | 0 src/test/ui/{ => linkage-attr}/linkage4.rs | 0 .../ui/{ => linkage-attr}/linkage4.stderr | 0 .../ui/lint/issue-54538-unused-parens-lint.rs | 28 +- .../issue-54538-unused-parens-lint.stderr | 52 +- src/test/ui/lint/lint-ctypes-enum.rs | 47 +- src/test/ui/lint/lint-ctypes-enum.stderr | 58 +- src/test/ui/lint/lint-ctypes.rs | 2 +- src/test/ui/lint/lint-ctypes.stderr | 14 +- src/test/ui/lint/lint-dead-code-3.rs | 2 +- src/test/ui/lint/lint-malformed.rs | 2 +- src/test/ui/lint/lint-malformed.stderr | 8 +- src/test/ui/lint/lint-match-arms.rs | 18 + src/test/ui/lint/lint-match-arms.stderr | 14 + src/test/ui/lint/lint-obsolete-attr.rs | 12 - src/test/ui/lint/lint-obsolete-attr.stderr | 20 - src/test/ui/lint/lint-stability-2.rs | 4 +- src/test/ui/lint/lint-stability-deprecated.rs | 6 +- src/test/ui/lint/lint-stability.rs | 6 +- src/test/ui/lint/lint-type-overflow2.rs | 16 +- src/test/ui/lint/lint-type-overflow2.stderr | 36 +- .../ui/lint/lint-unconditional-recursion.rs | 4 +- src/test/ui/lint/lint-unknown-attr.rs | 11 - src/test/ui/lint/lint-unknown-attr.stderr | 26 - src/test/ui/lint/lint-unnecessary-parens.rs | 4 +- .../ui/lint/lint-unnecessary-parens.stderr | 4 +- src/test/ui/lint/lint-unused-mut-variables.rs | 8 + .../ui/lint/lint-unused-mut-variables.stderr | 4 +- src/test/ui/lint/must_use-array.rs | 47 + src/test/ui/lint/must_use-array.stderr | 44 + src/test/ui/lint/must_use-trait.rs | 17 + src/test/ui/lint/must_use-trait.stderr | 28 +- src/test/ui/lint/must_use-tuple.rs | 17 + src/test/ui/lint/must_use-tuple.stderr | 47 + src/test/ui/lint/reasons-erroneous.rs | 12 +- src/test/ui/lint/reasons-erroneous.stderr | 46 +- .../loops-reject-lifetime-shadowing-label.rs | 2 +- ...ops-reject-lifetime-shadowing-label.stderr | 6 +- src/test/ui/lub-glb/old-lub-glb-object.rs | 10 +- src/test/ui/macros/format-parse-errors.stderr | 12 +- .../macro-at-most-once-rep-2015-ques-rep.rs | 13 - ...acro-at-most-once-rep-2015-ques-rep.stderr | 18 - .../macro-at-most-once-rep-2015-ques-sep.rs | 28 - ...acro-at-most-once-rep-2015-ques-sep.stderr | 24 - .../ui/macros/macro-at-most-once-rep-2015.rs | 42 + .../macros/macro-at-most-once-rep-2015.stderr | 107 + .../ui/macros/macro-at-most-once-rep-2018.rs | 1 + .../macros/macro-at-most-once-rep-2018.stderr | 24 +- src/test/ui/macros/macro-inner-attributes.rs | 4 +- .../macros/macro-input-future-proofing.stderr | 4 +- src/test/ui/macros/macro-outer-attributes.rs | 4 +- .../ui/macros/nonterminal-matching.stderr | 3 + .../ui/malformed/malformed-derive-entry.rs | 13 +- .../malformed/malformed-derive-entry.stderr | 14 +- .../ui/malformed/malformed-interpolated.rs | 6 +- .../malformed/malformed-interpolated.stderr | 12 +- src/test/ui/malformed/malformed-plugin-1.rs | 2 +- .../ui/malformed/malformed-plugin-1.stderr | 4 +- src/test/ui/malformed/malformed-plugin-2.rs | 2 +- .../ui/malformed/malformed-plugin-2.stderr | 4 +- src/test/ui/malformed/malformed-plugin-3.rs | 2 +- .../ui/malformed/malformed-plugin-3.stderr | 4 +- .../ui/malformed/malformed-special-attrs.rs | 6 +- .../malformed/malformed-special-attrs.stderr | 21 +- src/test/ui/malformed/malformed-unwind-1.rs | 6 +- .../ui/malformed/malformed-unwind-1.stderr | 10 +- src/test/ui/malformed/malformed-unwind-2.rs | 4 +- .../ui/malformed/malformed-unwind-2.stderr | 20 +- src/test/ui/map-types.rs | 4 +- src/test/ui/map-types.stderr | 6 +- .../marker-attribute-with-values.rs | 9 +- .../marker-attribute-with-values.stderr | 16 +- src/test/ui/match/match-fn-call.stderr | 8 +- .../ui/match/match-range-fail-dominate.rs | 18 +- .../ui/match/match-range-fail-dominate.stderr | 14 +- src/test/ui/maybe-bounds.rs | 9 +- src/test/ui/maybe-bounds.stderr | 12 +- ...method-ambig-one-trait-unknown-int-type.rs | 2 +- ...od-ambig-one-trait-unknown-int-type.stderr | 4 +- .../method-call-lifetime-args-lint-fail.rs | 4 +- src/test/ui/mismatched_types/cast-rfc0401.rs | 16 +- .../ui/mismatched_types/cast-rfc0401.stderr | 8 +- src/test/ui/mismatched_types/issue-19109.rs | 4 +- .../ui/mismatched_types/issue-19109.stderr | 8 +- .../trait-bounds-cant-coerce.rs | 6 +- src/test/ui/moves/move-out-of-array-1.stderr | 5 +- src/test/ui/moves/move-out-of-slice-1.stderr | 11 +- .../ui/moves/moves-based-on-type-block-bad.rs | 1 - .../moves-based-on-type-block-bad.stderr | 20 +- ...-move-out-of-closure-env-issue-1965.stderr | 4 +- ...ased-on-type-no-recursive-stack-closure.rs | 2 +- src/test/ui/nll/assign-while-to-immutable.rs | 11 + .../ui/nll/cannot-move-block-spans.stderr | 39 +- .../escape-upvar-nested.stderr | 12 +- .../escape-upvar-ref.stderr | 6 +- ...does-outlive-lbr2-because-implied-bound.rs | 5 +- src/test/ui/nll/dont-print-desugared.rs | 21 + src/test/ui/nll/dont-print-desugared.stderr | 27 + src/test/ui/nll/empty-type-predicate.rs | 11 + ...eport-when-borrow-and-drop-conflict.stderr | 1 + src/test/ui/nll/issue-52086.stderr | 4 +- ...issue-52663-span-decl-captured-variable.rs | 2 +- ...e-52663-span-decl-captured-variable.stderr | 4 +- src/test/ui/nll/issue-52663-trait-object.rs | 2 +- .../ui/nll/issue-52663-trait-object.stderr | 4 +- src/test/ui/nll/issue-53570.rs | 4 +- src/test/ui/nll/issue-57960.rs | 6 +- src/test/ui/nll/issue-61311-normalize.rs | 34 + src/test/ui/nll/issue-61320-normalize.rs | 160 + src/test/ui/nll/issue-61424.rs | 7 + src/test/ui/nll/issue-61424.stderr | 16 + .../ui/nll/issue-62007-assign-const-index.rs | 32 + .../nll/issue-62007-assign-const-index.stderr | 27 + .../issue-62007-assign-differing-fields.rs | 25 + ...issue-62007-assign-differing-fields.stderr | 27 + src/test/ui/nll/match-guards-always-borrow.rs | 2 +- .../ui/nll/match-guards-always-borrow.stderr | 12 +- src/test/ui/nll/move-errors.stderr | 99 +- .../adt-tuple-struct-calls.rs | 71 + .../adt-tuple-struct-calls.stderr | 56 + src/test/ui/no_crate_type.rs | 2 +- src/test/ui/no_crate_type.stderr | 4 +- src/test/ui/numeric/numeric-fields.stderr | 9 +- src/test/ui/object-does-not-impl-trait.rs | 2 +- src/test/ui/object-does-not-impl-trait.stderr | 6 +- .../object-lifetime-default-ambiguous.rs | 12 +- .../object-lifetime-default-ambiguous.stderr | 14 +- ...object-lifetime-default-elision.nll.stderr | 2 +- .../object-lifetime-default-elision.rs | 10 +- .../object-lifetime-default-elision.stderr | 8 +- ...lifetime-default-from-box-error.nll.stderr | 8 +- .../object-lifetime-default-from-box-error.rs | 8 +- ...ect-lifetime-default-from-box-error.stderr | 4 +- ...ime-default-from-rptr-box-error.nll.stderr | 2 +- ...ct-lifetime-default-from-rptr-box-error.rs | 4 +- ...ifetime-default-from-rptr-box-error.stderr | 2 +- ...-default-from-rptr-struct-error.nll.stderr | 2 +- ...lifetime-default-from-rptr-struct-error.rs | 6 +- ...time-default-from-rptr-struct-error.stderr | 2 +- .../object-lifetime-default-mybox.nll.stderr | 4 +- .../object-lifetime-default-mybox.rs | 10 +- .../object-lifetime-default-mybox.stderr | 12 +- src/test/ui/object-pointer-types.rs | 6 +- .../object-safety-associated-consts.rs | 2 +- .../object-safety-associated-consts.stderr | 4 +- .../object-safety-by-value-self-use.rs | 2 +- .../object-safety-by-value-self.rs | 18 +- .../object-safety/object-safety-generics.rs | 12 +- .../object-safety-generics.stderr | 8 +- .../object-safety-issue-22040.rs | 6 +- .../object-safety-issue-22040.stderr | 4 +- .../object-safety-mentions-Self.rs | 10 +- .../object-safety-mentions-Self.stderr | 8 +- .../object-safety/object-safety-no-static.rs | 2 +- .../object-safety-no-static.stderr | 4 +- .../object-safety/object-safety-phantom-fn.rs | 4 +- .../ui/object-safety/object-safety-sized-2.rs | 2 +- .../object-safety-sized-2.stderr | 4 +- .../ui/object-safety/object-safety-sized.rs | 2 +- .../object-safety/object-safety-sized.stderr | 4 +- .../object-safety-supertrait-mentions-Self.rs | 4 +- ...ect-safety-supertrait-mentions-Self.stderr | 4 +- src/test/ui/obsolete-in-place/bad.bad.stderr | 23 +- src/test/ui/obsolete-in-place/bad.rs | 15 +- src/test/ui/obsolete-in-place/bad.stderr | 27 + .../old-suffixes-are-really-forbidden.stderr | 4 +- .../ui/on-unimplemented/bad-annotation.rs | 2 +- .../ui/on-unimplemented/bad-annotation.stderr | 8 +- ...ciated-types-project-from-hrtb-explicit.rs | 2 - ...ed-types-project-from-hrtb-explicit.stderr | 4 +- src/test/ui/parser/bad-lit-suffixes.rs | 7 +- src/test/ui/parser/bad-lit-suffixes.stderr | 36 +- src/test/ui/parser/bounds-obj-parens.rs | 2 + src/test/ui/parser/bounds-type.rs | 2 +- src/test/ui/parser/doc-after-struct-field.rs | 2 - .../ui/parser/doc-after-struct-field.stderr | 4 +- src/test/ui/parser/doc-before-fn-rbrace.rs | 2 - .../ui/parser/doc-before-fn-rbrace.stderr | 2 +- src/test/ui/parser/doc-before-identifier.rs | 2 - .../ui/parser/doc-before-identifier.stderr | 2 +- src/test/ui/parser/doc-before-mod-rbrace.rs | 2 - .../ui/parser/doc-before-mod-rbrace.stderr | 2 +- .../ui/parser/doc-before-struct-rbrace-1.rs | 2 - .../parser/doc-before-struct-rbrace-1.stderr | 2 +- .../ui/parser/doc-before-struct-rbrace-2.rs | 2 - .../parser/doc-before-struct-rbrace-2.stderr | 2 +- src/test/ui/parser/fn-arg-doc-comment.rs | 18 +- src/test/ui/parser/fn-arg-doc-comment.stderr | 46 +- src/test/ui/parser/if-in-in.stderr | 3 - .../ui/parser/int-literal-too-large-span.rs | 2 +- .../parser/int-literal-too-large-span.stderr | 2 +- src/test/ui/parser/inverted-parameters.rs | 2 + src/test/ui/parser/inverted-parameters.stderr | 12 +- src/test/ui/parser/issue-17383.rs | 2 +- src/test/ui/parser/issue-17383.stderr | 11 +- src/test/ui/parser/issue-17904-2.rs | 2 - src/test/ui/parser/issue-17904-2.stderr | 2 +- src/test/ui/parser/issue-17904.rs | 2 - src/test/ui/parser/issue-17904.stderr | 2 +- src/test/ui/parser/issue-32214.rs | 2 - src/test/ui/parser/issue-32214.stderr | 2 +- src/test/ui/parser/issue-32505.rs | 2 - src/test/ui/parser/issue-32505.stderr | 2 +- src/test/ui/parser/issue-5544-a.rs | 2 +- src/test/ui/parser/issue-5544-a.stderr | 2 +- src/test/ui/parser/issue-5544-b.rs | 2 +- src/test/ui/parser/issue-5544-b.stderr | 2 +- src/test/ui/parser/issue-62546.rs | 3 + src/test/ui/parser/issue-62546.stderr | 17 + src/test/ui/parser/issue-62660.rs | 11 + src/test/ui/parser/issue-62660.stderr | 8 + src/test/ui/parser/issue-62881.rs | 6 + src/test/ui/parser/issue-62881.stderr | 29 + src/test/ui/parser/issue-62895.rs | 11 + src/test/ui/parser/issue-62895.stderr | 49 + src/test/ui/parser/lex-bad-binary-literal.rs | 2 - .../ui/parser/lex-bad-binary-literal.stderr | 18 +- .../ui/parser/lex-bad-numeric-literals.rs | 8 +- .../ui/parser/lex-bad-numeric-literals.stderr | 32 +- src/test/ui/parser/lex-bad-octal-literal.rs | 2 - .../ui/parser/lex-bad-octal-literal.stderr | 4 +- ...-bare-cr-string-literal-doc-comment.stderr | 6 +- .../ui/parser/macro/bad-macro-argument.rs | 4 + .../ui/parser/macro/bad-macro-argument.stderr | 8 + src/test/ui/parser/macro/issue-33569.rs | 2 +- src/test/ui/parser/macro/issue-33569.stderr | 2 +- .../ui/parser/macro/macro-incomplete-parse.rs | 2 - .../macro/macro-incomplete-parse.stderr | 6 +- src/test/ui/parser/new-unicode-escapes-4.rs | 2 - .../ui/parser/new-unicode-escapes-4.stderr | 2 +- src/test/ui/parser/no-binary-float-literal.rs | 2 +- .../ui/parser/no-binary-float-literal.stderr | 2 +- src/test/ui/parser/no-unsafe-self.rs | 2 - src/test/ui/parser/no-unsafe-self.stderr | 12 +- .../ui/parser/omitted-arg-in-item-fn.stderr | 10 + .../ui/parser/range_inclusive_dotdotdot.rs | 2 - .../parser/range_inclusive_dotdotdot.stderr | 8 +- .../ui/parser/raw-byte-string-literals.rs | 4 +- .../ui/parser/raw-byte-string-literals.stderr | 10 +- src/test/ui/parser/recover-enum.rs | 2 - src/test/ui/parser/recover-enum.stderr | 6 +- src/test/ui/parser/recover-enum2.rs | 2 - src/test/ui/parser/recover-enum2.stderr | 4 +- .../ui/parser/recover-from-bad-variant.stderr | 2 +- src/test/ui/parser/recover-struct.rs | 2 - src/test/ui/parser/recover-struct.stderr | 2 +- .../ui/parser/removed-syntax-field-let.rs | 2 - .../ui/parser/removed-syntax-field-let.stderr | 4 +- src/test/ui/parser/self-in-function-arg.rs | 3 + .../ui/parser/self-in-function-arg.stderr | 10 + .../ui/parser/tag-variant-disr-non-nullary.rs | 3 +- .../tag-variant-disr-non-nullary.stderr | 20 +- src/test/ui/parser/trailing-plus-in-bounds.rs | 2 +- .../ui/parser/trait-bounds-not-on-impl.rs | 8 +- .../ui/parser/trait-bounds-not-on-impl.stderr | 4 +- src/test/ui/parser/trait-object-bad-parens.rs | 3 +- .../ui/parser/trait-object-bad-parens.stderr | 8 +- .../ui/parser/trait-object-lifetime-parens.rs | 2 +- .../parser/trait-object-polytrait-priority.rs | 2 + .../trait-object-polytrait-priority.stderr | 2 +- .../ui/parser/trait-object-trait-parens.rs | 7 +- .../parser/trait-object-trait-parens.stderr | 24 +- .../ui/parser/underscore_item_not_const.rs | 30 + .../parser/underscore_item_not_const.stderr | 92 + src/test/ui/parser/underscore_static.rs | 3 - src/test/ui/parser/underscore_static.stderr | 8 - .../use-as-where-use-ends-with-mod-sep.rs | 2 - .../use-as-where-use-ends-with-mod-sep.stderr | 4 +- .../where-clauses-no-bounds-or-predicates.rs | 2 - ...ere-clauses-no-bounds-or-predicates.stderr | 2 +- src/test/ui/pattern/const-pat-ice.rs | 1 + src/test/ui/pattern/const-pat-ice.stderr | 4 +- .../pattern/pattern-bindings-after-at.stderr | 1 + src/test/ui/pattern/slice-pattern-const-2.rs | 4 +- .../ui/pattern/slice-pattern-const-2.stderr | 20 +- src/test/ui/placement-syntax.rs | 3 +- src/test/ui/placement-syntax.stderr | 14 +- src/test/ui/print_type_sizes/generics.rs | 3 + src/test/ui/print_type_sizes/niche-filling.rs | 3 + src/test/ui/print_type_sizes/no_duplicates.rs | 3 + src/test/ui/print_type_sizes/packed.rs | 3 + src/test/ui/print_type_sizes/repr-align.rs | 3 + src/test/ui/print_type_sizes/uninhabited.rs | 3 + .../private-in-public-non-principal-2.rs | 2 +- .../private-in-public-non-principal.rs | 2 +- .../private-in-public-non-principal.stderr | 4 +- src/test/ui/privacy/private-inferred-type.rs | 6 +- src/test/ui/proc-macro/attr-invalid-exprs.rs | 2 +- .../ui/proc-macro/attr-invalid-exprs.stderr | 2 +- .../proc-macro/attribute-order-restricted.rs | 10 +- .../attribute-order-restricted.stderr | 4 +- .../ui/proc-macro/attribute-with-error.rs | 17 +- .../ui/proc-macro/attribute-with-error.stderr | 8 +- src/test/ui/proc-macro/attribute.rs | 10 +- src/test/ui/proc-macro/attribute.stderr | 42 +- .../proc-macro/auxiliary/attr_proc_macro.rs | 13 - .../auxiliary/attribute-with-error.rs | 13 - .../proc-macro/auxiliary/bang_proc_macro.rs | 13 - .../ui/proc-macro/auxiliary/derive-a-b.rs | 17 - src/test/ui/proc-macro/auxiliary/derive-a.rs | 13 - .../auxiliary/derive-helper-shadowed-2.rs | 2 +- .../auxiliary/derive-helper-shadowed.rs | 12 - .../auxiliary/derive-helper-shadowing.rs | 17 - .../ui/proc-macro/auxiliary/derive-panic.rs | 13 - .../auxiliary/dollar-crate-external.rs | 6 +- .../ui/proc-macro/auxiliary/dollar-crate.rs | 35 - .../ui/proc-macro/auxiliary/generate-mod.rs | 1 + .../ui/proc-macro/auxiliary/issue-41211.rs | 12 - .../ui/proc-macro/auxiliary/issue-53481.rs | 13 - .../ui/proc-macro/auxiliary/macro-brackets.rs | 12 - .../proc-macro/auxiliary/nested-item-spans.rs | 13 - .../proc-macro/auxiliary/proc-macro-gates.rs | 18 - .../proc-macro/auxiliary/span-preservation.rs | 13 - .../ui/proc-macro/auxiliary/test-macros.rs | 104 +- .../ui/proc-macro/derive-helper-shadowed.rs | 12 +- .../ui/proc-macro/derive-helper-shadowing.rs | 20 +- .../proc-macro/derive-helper-shadowing.stderr | 34 +- src/test/ui/proc-macro/derive-in-mod.rs | 13 + src/test/ui/proc-macro/derive-still-gated.rs | 8 +- .../ui/proc-macro/derive-still-gated.stderr | 8 +- .../ui/proc-macro/dollar-crate-issue-57089.rs | 9 +- .../dollar-crate-issue-57089.stdout | 9 +- src/test/ui/proc-macro/dollar-crate.rs | 13 +- src/test/ui/proc-macro/dollar-crate.stderr | 4 +- src/test/ui/proc-macro/dollar-crate.stdout | 28 +- .../helper-attr-blocked-by-import-ambig.rs | 11 + ...helper-attr-blocked-by-import-ambig.stderr | 21 + .../helper-attr-blocked-by-import.rs | 28 + src/test/ui/proc-macro/import.rs | 11 +- src/test/ui/proc-macro/import.stderr | 8 +- src/test/ui/proc-macro/invalid-attributes.rs | 12 +- .../ui/proc-macro/invalid-attributes.stderr | 24 +- src/test/ui/proc-macro/issue-36935.rs | 12 + src/test/ui/proc-macro/issue-36935.stderr | 10 + src/test/ui/proc-macro/issue-37788.rs | 4 +- src/test/ui/proc-macro/issue-41211.rs | 10 +- src/test/ui/proc-macro/issue-41211.stderr | 10 +- src/test/ui/proc-macro/issue-53481.rs | 14 +- src/test/ui/proc-macro/load-panic.rs | 7 +- src/test/ui/proc-macro/load-panic.stderr | 8 +- src/test/ui/proc-macro/macro-brackets.rs | 8 +- src/test/ui/proc-macro/macro-use-attr.rs | 7 +- src/test/ui/proc-macro/macro-use-bang.rs | 6 +- src/test/ui/proc-macro/macros-in-extern.rs | 9 +- .../ui/proc-macro/macros-in-extern.stderr | 18 +- src/test/ui/proc-macro/nested-item-spans.rs | 11 +- .../ui/proc-macro/nested-item-spans.stderr | 4 +- src/test/ui/proc-macro/no-macro-use-attr.rs | 4 +- .../ui/proc-macro/no-macro-use-attr.stderr | 4 +- src/test/ui/proc-macro/proc-macro-gates.rs | 43 +- .../ui/proc-macro/proc-macro-gates.stderr | 98 +- src/test/ui/proc-macro/proc-macro-gates2.rs | 11 +- .../ui/proc-macro/proc-macro-gates2.stderr | 16 +- src/test/ui/proc-macro/resolve-error.rs | 18 +- src/test/ui/proc-macro/resolve-error.stderr | 37 +- src/test/ui/proc-macro/shadow.rs | 6 +- src/test/ui/proc-macro/shadow.stderr | 12 +- src/test/ui/proc-macro/span-preservation.rs | 17 +- .../ui/proc-macro/span-preservation.stderr | 10 +- src/test/ui/question-mark-type-infer.stderr | 1 + src/test/ui/recursion/recursion.stderr | 2 +- ...recursive-types-are-not-uninhabited.stderr | 1 + .../region-borrow-params-issue-29793-small.rs | 30 +- ...n-bounds-on-objects-and-type-parameters.rs | 16 +- ...unds-on-objects-and-type-parameters.stderr | 10 +- .../region-object-lifetime-2.nll.stderr | 2 +- .../ui/regions/region-object-lifetime-2.rs | 2 +- .../regions/region-object-lifetime-2.stderr | 4 +- .../region-object-lifetime-4.nll.stderr | 2 +- .../ui/regions/region-object-lifetime-4.rs | 2 +- .../regions/region-object-lifetime-4.stderr | 4 +- .../ui/regions/region-object-lifetime-5.rs | 2 +- ...ion-object-lifetime-in-coercion.nll.stderr | 12 +- .../region-object-lifetime-in-coercion.rs | 12 +- .../region-object-lifetime-in-coercion.stderr | 16 +- ...gions-close-associated-type-into-object.rs | 16 +- ...ions-close-object-into-object-2.nll.stderr | 10 +- .../regions-close-object-into-object-2.rs | 6 +- .../regions-close-object-into-object-2.stderr | 6 +- ...ions-close-object-into-object-4.nll.stderr | 14 +- .../regions-close-object-into-object-4.rs | 6 +- .../regions-close-object-into-object-4.stderr | 6 +- ...ons-close-over-type-parameter-1.nll.stderr | 4 +- .../regions-close-over-type-parameter-1.rs | 12 +- ...regions-close-over-type-parameter-1.stderr | 32 +- ...se-over-type-parameter-multiple.nll.stderr | 6 +- ...ions-close-over-type-parameter-multiple.rs | 12 +- ...-close-over-type-parameter-multiple.stderr | 12 +- .../regions-close-param-into-object.rs | 8 +- .../regions-close-param-into-object.stderr | 8 +- ...ions-implied-bounds-projection-gap-hr-1.rs | 2 +- ...-implied-bounds-projection-gap-hr-1.stderr | 6 +- .../regions/regions-infer-at-fn-not-param.rs | 6 +- ...ns-infer-invariance-due-to-mutability-3.rs | 2 +- ...ns-infer-invariance-due-to-mutability-4.rs | 2 +- .../ui/regions/regions-infer-not-param.rs | 4 +- .../ui/regions/regions-name-undeclared.rs | 6 +- .../ui/regions/regions-nested-fns.nll.stderr | 8 +- src/test/ui/regions/regions-nested-fns.rs | 4 +- src/test/ui/regions/regions-nested-fns.stderr | 24 +- .../ui/regions/regions-proc-bound-capture.rs | 4 +- .../regions/regions-proc-bound-capture.stderr | 2 +- src/test/ui/regions/regions-steal-closure.rs | 4 +- src/test/ui/regions/regions-trait-1.rs | 4 +- .../regions-trait-object-subtyping.nll.stderr | 4 +- .../regions/regions-trait-object-subtyping.rs | 8 +- .../regions-trait-object-subtyping.stderr | 12 +- src/test/ui/regions/regions-trait-variance.rs | 4 +- .../ui/regions/regions-wf-trait-object.rs | 2 +- .../ui/regions/regions-wf-trait-object.stderr | 4 +- src/test/ui/repr.rs | 9 +- src/test/ui/repr.stderr | 16 +- src/test/ui/repr/repr-align.rs | 20 +- src/test/ui/repr/repr-align.stderr | 22 +- .../ui/repr/repr-transparent-other-items.rs | 21 - .../repr/repr-transparent-other-items.stderr | 64 +- src/test/ui/repr/repr-transparent.rs | 34 +- src/test/ui/repr/repr-transparent.stderr | 106 +- src/test/ui/resolve/issue-23305.rs | 2 +- src/test/ui/resolve/issue-23305.stderr | 10 +- src/test/ui/resolve/issue-33876.rs | 2 +- src/test/ui/resolve/issue-33876.stderr | 6 +- src/test/ui/resolve/issue-3907-2.rs | 2 +- src/test/ui/resolve/issue-3907.rs | 2 +- src/test/ui/resolve/issue-5035-2.rs | 2 +- src/test/ui/resolve/issue-5035.rs | 2 +- .../rfc-reject-double-move-across-arms.rs | 2 +- .../rfc-reject-double-move-across-arms.stderr | 6 +- .../rfc-reject-double-move-in-first-arm.rs | 2 +- ...rfc-reject-double-move-in-first-arm.stderr | 6 +- .../ui/rfc-2005-default-binding-mode/for.rs | 2 +- .../rfc-2005-default-binding-mode/for.stderr | 11 +- .../invalid-attribute.rs | 2 +- .../invalid-attribute.stderr | 4 +- ...tch_with_exhaustive_patterns_same_crate.rs | 4 +- ...tch_with_exhaustive_patterns_same_crate.rs | 4 +- .../rfc-2093-infer-outlives/self-structs.rs | 2 +- .../self-structs.stderr | 2 +- .../ast-pretty-check.rs | 6 + .../ast-pretty-check.stdout | 10 + .../disallowed-positions.rs | 244 + .../disallowed-positions.stderr | 987 + .../ui/rfc-2497-if-let-chains/feature-gate.rs | 136 + .../feature-gate.stderr | 570 + .../protect-precedences.rs | 18 + .../syntax-ambiguity-2015.rs | 38 - .../syntax-ambiguity-2015.stderr | 56 - .../syntax-ambiguity-2018.rs | 38 - .../syntax-ambiguity-2018.stderr | 56 - .../rfc-2565-param-attrs/param-attrs-2018.rs | 8 + .../param-attrs-2018.stderr | 18 + .../param-attrs-allowed.rs | 225 + .../param-attrs-builtin-attrs.rs | 145 + .../param-attrs-builtin-attrs.stderr | 339 + .../rfc-2565-param-attrs/param-attrs-cfg.rs | 79 + .../param-attrs-cfg.stderr | 68 + .../param-attrs-feature-gate.rs | 14 + .../param-attrs-feature-gate.stderr | 27 + .../generic-associated-types-where.rs | 4 +- src/test/ui/rfc1623.rs | 2 +- .../edition-lint-infer-outlives-multispan.rs | 377 +- ...ition-lint-infer-outlives-multispan.stderr | 682 +- .../edition-lint-infer-outlives.fixed | 819 +- .../rust-2018/edition-lint-infer-outlives.rs | 819 +- .../edition-lint-infer-outlives.stderr | 910 +- .../emit-notifications.nll.stderr | 2 + .../ui/save-analysis/emit-notifications.rs | 7 + .../save-analysis/emit-notifications.stderr | 2 + src/test/ui/save-analysis/issue-59134-0.rs | 2 +- .../arbitrary-self-types-not-object-safe.rs | 4 +- ...rbitrary-self-types-not-object-safe.stderr | 6 +- .../self/arbitrary_self_types_pin_lifetime.rs | 2 +- ...f_types_pin_lifetime_impl_trait.nll.stderr | 2 +- .../arbitrary_self_types_raw_pointer_trait.rs | 8 +- src/test/ui/self/elision/README.md | 44 + src/test/ui/self/elision/alias.rs | 36 + src/test/ui/self/elision/assoc.rs | 40 + src/test/ui/self/elision/lt-alias.rs | 38 + src/test/ui/self/elision/lt-assoc.rs | 44 + .../ui/self/elision/lt-ref-self.nll.stderr | 62 + src/test/ui/self/elision/lt-ref-self.rs | 38 + src/test/ui/self/elision/lt-ref-self.stderr | 62 + src/test/ui/self/elision/lt-self.rs | 49 + src/test/ui/self/elision/lt-struct.rs | 36 + src/test/ui/self/elision/multiple-ref-self.rs | 43 + src/test/ui/self/elision/ref-alias.rs | 39 + src/test/ui/self/elision/ref-assoc.rs | 40 + src/test/ui/self/elision/ref-mut-alias.rs | 36 + .../ui/self/elision/ref-mut-self.nll.stderr | 62 + src/test/ui/self/elision/ref-mut-self.rs | 38 + src/test/ui/self/elision/ref-mut-self.stderr | 62 + .../ui/self/elision/ref-mut-struct.nll.stderr | 52 + src/test/ui/self/elision/ref-mut-struct.rs | 32 + .../ui/self/elision/ref-mut-struct.stderr | 52 + src/test/ui/self/elision/ref-self.nll.stderr | 72 + src/test/ui/self/elision/ref-self.rs | 51 + src/test/ui/self/elision/ref-self.stderr | 72 + .../ui/self/elision/ref-struct.nll.stderr | 52 + src/test/ui/self/elision/ref-struct.rs | 32 + src/test/ui/self/elision/ref-struct.stderr | 52 + src/test/ui/self/elision/self.rs | 36 + src/test/ui/self/elision/struct.rs | 32 + .../ui/self/explicit-self-objects-uniq.rs | 2 +- .../object-safety-sized-self-by-value-self.rs | 2 +- ...object-safety-sized-self-generic-method.rs | 2 +- .../object-safety-sized-self-return-Self.rs | 2 +- src/test/ui/self/self_lifetime.rs | 4 +- src/test/ui/self/self_type_keyword.rs | 2 - src/test/ui/self/self_type_keyword.stderr | 22 +- .../one-use-in-fn-return.rs | 14 +- .../single-use-lifetime/one-use-in-struct.rs | 7 + .../borrowck-call-is-borrow-issue-12224.rs | 10 +- ...borrowck-call-is-borrow-issue-12224.stderr | 6 +- .../ui/span/borrowck-object-mutability.rs | 8 +- .../ui/span/borrowck-object-mutability.stderr | 6 +- src/test/ui/span/dropck-object-cycle.rs | 8 +- src/test/ui/span/issue-25199.rs | 2 +- src/test/ui/span/issue-26656.rs | 2 +- src/test/ui/span/issue-34264.stderr | 20 + .../issue-42234-unknown-receiver-type.stderr | 4 +- .../regions-close-over-borrowed-ref-in-obj.rs | 2 +- .../regions-close-over-type-parameter-2.rs | 4 +- .../send-is-not-static-ensures-scoping.rs | 2 +- .../specialization-overlap-hygiene.stderr | 1 + .../stability-attribute-sanity-4.rs | 12 +- .../stability-attribute-sanity-4.stderr | 24 +- .../ui/static/static-items-cant-move.stderr | 4 +- src/test/ui/std-uncopyable-atomics.rs | 8 +- src/test/ui/std-uncopyable-atomics.stderr | 24 +- src/test/ui/stmt_expr_attrs_no_feature.rs | 61 +- src/test/ui/stmt_expr_attrs_no_feature.stderr | 54 +- src/test/ui/suffixed-literal-meta.rs | 28 +- src/test/ui/suffixed-literal-meta.stderr | 72 +- .../suggestions/borrow-for-loop-head.stderr | 9 +- .../duplicate-suggestions.stderr | 66 +- .../dont-suggest-ref/move-into-closure.stderr | 342 +- .../ui/suggestions/dont-suggest-ref/simple.rs | 22 +- .../dont-suggest-ref/simple.stderr | 772 +- src/test/ui/suggestions/issue-52820.rs | 12 + src/test/ui/suggestions/issue-52820.stderr | 27 + .../ui/suggestions/mut-ref-reassignment.rs | 17 + .../suggestions/mut-ref-reassignment.stderr | 47 + .../ui/suggestions/option-content-move.fixed | 39 + .../ui/suggestions/option-content-move.rs | 39 + .../ui/suggestions/option-content-move.stderr | 21 + ...use-type-argument-instead-of-assoc-type.rs | 2 +- ...type-argument-instead-of-assoc-type.stderr | 18 +- src/test/ui/symbol-names/basic.legacy.stderr | 26 + src/test/ui/symbol-names/basic.rs | 16 +- src/test/ui/symbol-names/basic.v0.stderr | 26 + src/test/ui/symbol-names/impl1.legacy.stderr | 74 + src/test/ui/symbol-names/impl1.rs | 61 +- src/test/ui/symbol-names/impl1.v0.stderr | 74 + src/test/ui/symbol-names/impl2.rs | 14 + src/test/ui/symbol-names/impl2.stderr | 8 + .../ui/symbol-names/issue-60925.legacy.stderr | 20 + src/test/ui/symbol-names/issue-60925.rs | 49 + src/test/ui/symbol-names/issue-60925.stderr | 20 + .../ui/symbol-names/issue-60925.v0.stderr | 20 + src/test/ui/target-feature-wrong.rs | 16 +- src/test/ui/target-feature-wrong.stderr | 31 +- src/test/ui/thread-local-in-ctfe.stderr | 2 + .../tool-attributes-misplaced-1.rs | 5 +- .../tool-attributes-misplaced-1.stderr | 26 +- src/test/ui/traits/trait-alias-object.rs | 9 - .../auxiliary/trait_alias.rs | 0 .../traits/trait-alias}/trait-alias-bounds.rs | 4 +- .../trait-alias-cross-crate.rs | 0 .../trait-alias-cross-crate.stderr | 0 .../{ => trait-alias}/trait-alias-impl.rs | 0 .../{ => trait-alias}/trait-alias-impl.stderr | 0 .../trait-alias/trait-alias-maybe-bound.rs | 29 + .../trait-alias/trait-alias-no-duplicates.rs | 126 + .../trait-alias-no-duplicates.stderr | 458 + .../trait-alias-no-extra-traits.rs | 121 + .../trait-alias-no-extra-traits.stderr | 513 + .../trait-alias/trait-alias-object-fail.rs | 11 + .../trait-alias-object-fail.stderr} | 8 +- .../trait-alias/trait-alias-object-wf.rs | 85 + .../traits/trait-alias}/trait-alias-object.rs | 2 + .../trait-alias-only-maybe-bound.rs | 22 + .../trait-alias-only-maybe-bound.stderr | 14 + .../trait-alias-syntax-fail.rs} | 0 .../trait-alias-syntax-fail.stderr} | 4 +- .../traits/trait-alias}/trait-alias-syntax.rs | 2 + .../{ => trait-alias}/trait-alias-wf.rs | 0 .../{ => trait-alias}/trait-alias-wf.stderr | 0 .../trait-alias}/trait-alias.rs | 1 + .../traits/trait-bounds-not-on-bare-trait.rs | 1 + .../trait-bounds-not-on-bare-trait.stderr | 8 + src/test/ui/traits/trait-bounds-sugar.rs | 8 +- .../ui/traits/trait-coercion-generic-bad.rs | 2 +- .../traits/trait-coercion-generic-bad.stderr | 6 +- .../traits/trait-coercion-generic-regions.rs | 2 +- .../trait-coercion-generic-regions.stderr | 2 +- src/test/ui/traits/trait-impl-1.rs | 2 +- src/test/ui/traits/trait-item-privacy.rs | 6 +- .../traits/trait-object-auto-dedup-in-impl.rs | 8 +- .../trait-object-auto-dedup-in-impl.stderr | 1 + .../ui/traits/trait-object-macro-matcher.rs | 7 +- .../traits/trait-object-macro-matcher.stderr | 12 +- src/test/ui/traits/trait-object-safety.rs | 2 +- src/test/ui/traits/trait-object-safety.stderr | 10 +- .../ui/traits/trait-object-vs-lifetime-2.rs | 6 +- .../traits/trait-object-vs-lifetime-2.stderr | 8 +- .../ui/traits/trait-object-vs-lifetime.rs | 8 +- .../ui/traits/trait-object-vs-lifetime.stderr | 18 +- src/test/ui/traits/trait-test-2.rs | 2 +- src/test/ui/traits/trait-test-2.stderr | 6 +- src/test/ui/traits/trait-with-dst.rs | 22 + .../traits-repeated-supertrait-ambig.rs | 2 +- .../traits-static-outlives-a-where-clause.rs | 0 .../ui/traits/wf-trait-object-maybe-bound.rs | 20 + .../traits/wf-trait-object-maybe-bound.stderr | 32 + .../traits/wf-trait-object-no-duplicates.rs | 33 + .../wf-trait-object-no-duplicates.stderr | 58 + .../wf-trait-object-only-maybe-bound.rs | 7 + .../wf-trait-object-only-maybe-bound.stderr | 14 + .../traits/wf-trait-object-reverse-order.rs | 15 + .../trivial-bounds-inconsistent-sized.rs | 4 +- .../trivial-bounds-inconsistent-sized.stderr | 6 +- .../trivial-bounds-inconsistent.rs | 4 +- .../trivial-bounds-inconsistent.stderr | 6 +- .../trivial-bounds-leak-copy.stderr | 4 +- src/test/ui/trivial_casts.rs | 28 +- src/test/ui/trivial_casts.stderr | 28 +- src/test/ui/tuple/tuple-arity-mismatch.rs | 2 +- src/test/ui/tuple/tuple-arity-mismatch.stderr | 2 +- src/test/ui/type-alias-enum-variants-panic.rs | 17 - .../ui/type-alias-enum-variants-panic.stderr | 21 - .../ui/type-alias-enum-variants-priority-2.rs | 13 - ...type-alias-enum-variants-priority-2.stderr | 12 - .../ui/type-alias-enum-variants-priority-3.rs | 10 - .../ui/type-alias-enum-variants-priority.rs | 19 - src/test/ui/type-alias-enum-variants.rs | 11 - .../enum-variant-generic-args-pass.rs} | 22 +- .../enum-variant-generic-args.rs | 36 +- .../enum-variant-generic-args.stderr | 124 +- ...ant-priority-higher-than-other-inherent.rs | 23 + ...priority-higher-than-other-inherent.stderr | 22 + ...riority-lint-ambiguous_associated_items.rs | 37 + ...ty-lint-ambiguous_associated_items.stderr} | 6 +- ...-variant-form-through-Self-issue-58006.rs} | 1 - ...iant-form-through-Self-issue-58006.stderr} | 2 +- ...rrect-variant-form-through-alias-caught.rs | 21 + ...t-variant-form-through-alias-caught.stderr | 43 + .../issue-57866.rs | 2 - .../issue-61801-path-pattern-can-infer.rs | 28 + ...ype-application-on-aliased-enum-variant.rs | 14 + ...pplication-on-aliased-enum-variant.stderr} | 4 +- ...num-variant-in-type-namespace-and-error.rs | 11 + ...ariant-in-type-namespace-and-error.stderr} | 2 +- .../type-alias-enum-variants-pass.rs | 69 + .../ui/type-alias/issue-62263-self-in-atb.rs | 8 + .../type-alias/issue-62263-self-in-atb.stderr | 9 + .../type-alias/issue-62305-self-assoc-ty.rs | 4 + .../issue-62305-self-assoc-ty.stderr | 9 + .../ui/type-alias/issue-62364-self-ty-arg.rs | 8 + .../type-alias/issue-62364-self-ty-arg.stderr | 9 + src/test/ui/type/type-alias-bounds.rs | 36 +- src/test/ui/type/type-alias-bounds.stderr | 12 +- src/test/ui/type/type-arg-out-of-scope.rs | 2 +- src/test/ui/type/type-arg-out-of-scope.stderr | 12 +- ...ascription-instead-of-statement-end.stderr | 2 +- .../cannot_infer_local_or_array.stderr | 4 +- .../cannot_infer_local_or_vec.stderr | 4 +- ...cannot_infer_local_or_vec_in_tuples.stderr | 4 +- .../ui/type/type-dependent-def-issue-49241.rs | 1 + .../type-dependent-def-issue-49241.stderr | 12 +- ...rameter-defaults-referencing-Self-ppaux.rs | 2 +- ...ter-defaults-referencing-Self-ppaux.stderr | 10 +- ...ype-parameter-defaults-referencing-Self.rs | 2 +- ...parameter-defaults-referencing-Self.stderr | 6 +- src/test/ui/type_length_limit.stderr | 2 +- .../typeck-builtin-bound-type-parameters.rs | 2 +- ...ypeck-builtin-bound-type-parameters.stderr | 4 +- .../unboxed-closure-feature-gate.rs | 8 +- .../unboxed-closure-feature-gate.stderr | 6 +- .../unboxed-closure-illegal-move.stderr | 16 +- .../unboxed-closure-sugar-default.rs | 6 +- .../unboxed-closure-sugar-default.stderr | 4 +- .../unboxed-closure-sugar-equiv.rs | 34 +- .../unboxed-closure-sugar-equiv.stderr | 6 +- .../unboxed-closure-sugar-lifetime-elision.rs | 10 +- ...oxed-closure-sugar-lifetime-elision.stderr | 6 +- .../unboxed-closure-sugar-not-used-on-fn.rs | 2 +- ...nboxed-closure-sugar-not-used-on-fn.stderr | 6 +- .../unboxed-closure-sugar-region.rs | 6 +- .../unboxed-closure-sugar-region.stderr | 6 +- ...r-wrong-number-number-type-parameters-1.rs | 2 +- ...ong-number-number-type-parameters-1.stderr | 6 +- ...r-wrong-number-number-type-parameters-3.rs | 2 +- ...ong-number-number-type-parameters-3.stderr | 12 +- ...gar-wrong-number-number-type-parameters.rs | 2 +- ...wrong-number-number-type-parameters.stderr | 12 +- .../unboxed-closures-failed-recursive-fn-1.rs | 4 +- ...oxed-closures-failed-recursive-fn-1.stderr | 8 +- ...oxed-closures-failed-recursive-fn-2.stderr | 4 +- ...oxed-closures-recursive-fn-using-fn-mut.rs | 6 +- .../underscore-lifetime-binders.rs | 2 +- .../underscore-lifetime-binders.stderr | 14 +- src/test/ui/union/union-repr-c.stderr | 2 +- src/test/ui/unique-object-noncopyable.rs | 2 +- src/test/ui/unop-move-semantics.rs | 4 +- src/test/ui/unop-move-semantics.stderr | 8 +- src/test/ui/unrestricted-attribute-tokens.rs | 8 +- .../ui/unsized-locals/unsized-exprs2.stderr | 5 +- src/test/ui/unsized/unsized-enum2.rs | 16 +- src/test/ui/unsized/unsized-enum2.stderr | 16 +- src/test/ui/unused/unused-attr.rs | 33 +- src/test/ui/unused/unused-attr.stderr | 90 +- ...use-after-move-implicity-coerced-object.rs | 4 +- ...riance-contravariant-arg-object.nll.stderr | 4 +- .../variance-contravariant-arg-object.rs | 8 +- .../variance-contravariant-arg-object.stderr | 8 +- .../variance-covariant-arg-object.nll.stderr | 4 +- .../variance/variance-covariant-arg-object.rs | 8 +- .../variance-covariant-arg-object.stderr | 8 +- .../variance-invariant-arg-object.nll.stderr | 4 +- .../variance/variance-invariant-arg-object.rs | 8 +- .../variance-invariant-arg-object.stderr | 8 +- src/test/ui/variance/variance-object-types.rs | 2 +- .../ui/variance/variance-object-types.stderr | 2 +- .../variance/variance-trait-object-bound.rs | 2 +- .../variance-trait-object-bound.stderr | 2 +- src/test/ui/variance/variance-types-bounds.rs | 4 +- .../ui/variance/variance-types-bounds.stderr | 4 +- src/test/ui/vector-no-ann.rs | 2 +- src/test/ui/vector-no-ann.stderr | 4 +- src/test/ui/wf/wf-in-obj-type-static.rs | 2 +- src/test/ui/wf/wf-in-obj-type-static.stderr | 8 +- src/test/ui/wf/wf-in-obj-type-trait.rs | 2 +- src/test/ui/wf/wf-in-obj-type-trait.stderr | 4 +- src/test/ui/wf/wf-object-safe.rs | 2 +- src/test/ui/wf/wf-object-safe.stderr | 4 +- .../ui/wf/wf-outlives-ty-in-fn-or-trait.rs | 2 +- .../wf/wf-outlives-ty-in-fn-or-trait.stderr | 8 +- .../where-lifetime-resolution.rs | 6 +- .../where-lifetime-resolution.stderr | 18 +- src/tools/build-manifest/src/main.rs | 1 + src/tools/cargotest/main.rs | 2 +- src/tools/compiletest/src/common.rs | 49 +- src/tools/compiletest/src/header.rs | 107 +- src/tools/compiletest/src/main.rs | 80 +- src/tools/compiletest/src/runtest.rs | 160 +- src/tools/error_index_generator/main.rs | 2 +- src/tools/publish_toolstate.py | 87 +- src/tools/rustbook/Cargo.toml | 5 +- src/tools/rustbook/src/main.rs | 14 +- src/tools/rustc-workspace-hack/Cargo.toml | 15 +- src/tools/tidy/Cargo.toml | 2 + src/tools/tidy/src/bins.rs | 7 +- src/tools/tidy/src/deps.rs | 11 +- src/tools/tidy/src/errors.rs | 9 +- src/tools/tidy/src/features.rs | 132 +- src/tools/tidy/src/lib.rs | 40 +- src/tools/tidy/src/libcoretest.rs | 25 +- src/tools/tidy/src/main.rs | 6 +- src/tools/tidy/src/pal.rs | 22 +- src/tools/tidy/src/style.rs | 30 +- src/tools/tidy/src/ui_tests.rs | 11 +- src/tools/tidy/src/unstable_book.rs | 38 +- vendor/ammonia/.cargo-checksum.json | 2 +- vendor/ammonia/CHANGELOG.md | 24 +- vendor/ammonia/Cargo.toml | 12 +- vendor/ammonia/LICENSE-MIT | 2 +- vendor/ammonia/README.md | 12 +- vendor/ammonia/src/lib.rs | 535 +- vendor/annotate-snippets/.cargo-checksum.json | 1 + vendor/annotate-snippets/Cargo.toml | 57 + .../LICENSE-APACHE | 5 +- vendor/annotate-snippets/LICENSE-MIT | 19 + vendor/annotate-snippets/README.md | 99 + .../examples/expected_type.rs | 42 + vendor/annotate-snippets/examples/footer.rs | 39 + vendor/annotate-snippets/examples/format.rs | 60 + .../annotate-snippets/examples/multislice.rs | 36 + .../src/display_list/from_snippet.rs | 403 + .../annotate-snippets/src/display_list/mod.rs | 124 + .../src/display_list/structs.rs | 253 + vendor/annotate-snippets/src/formatter/mod.rs | 345 + .../annotate-snippets/src/formatter/style.rs | 98 + vendor/annotate-snippets/src/lib.rs | 52 + vendor/annotate-snippets/src/snippet.rs | 81 + .../src/stylesheets/color.rs | 43 + .../annotate-snippets/src/stylesheets/mod.rs | 11 + .../src/stylesheets/no_color.rs | 21 + vendor/annotate-snippets/tests/diff/mod.rs | 46 + .../tests/dl_from_snippet.rs | 258 + vendor/annotate-snippets/tests/fixtures.rs | 62 + .../no-color/multiline_annotation.txt | 14 + .../no-color/multiline_annotation.yaml | 38 + .../no-color/multiline_annotation2.txt | 9 + .../no-color/multiline_annotation2.yaml | 16 + .../no-color/multiple_annotations.txt | 14 + .../no-color/multiple_annotations.yaml | 23 + .../tests/fixtures/no-color/simple.txt | 9 + .../tests/fixtures/no-color/simple.yaml | 17 + vendor/annotate-snippets/tests/formatter.rs | 497 + vendor/annotate-snippets/tests/snippet/mod.rs | 108 + vendor/autocfg/.cargo-checksum.json | 1 + vendor/autocfg/Cargo.toml | 24 + .../LICENSE-APACHE | 0 vendor/autocfg/LICENSE-MIT | 25 + vendor/autocfg/README.md | 75 + vendor/autocfg/examples/integers.rs | 9 + vendor/autocfg/examples/paths.rs | 22 + vendor/autocfg/examples/traits.rs | 26 + vendor/autocfg/examples/versions.rs | 9 + vendor/autocfg/src/error.rs | 69 + vendor/autocfg/src/lib.rs | 305 + vendor/autocfg/src/tests.rs | 65 + vendor/autocfg/src/version.rs | 60 + vendor/backtrace/.cargo-checksum.json | 2 +- vendor/backtrace/Cargo.toml | 61 +- vendor/backtrace/README.md | 24 +- vendor/backtrace/appveyor.yml | 26 - vendor/backtrace/azure-pipelines.yml | 158 + vendor/backtrace/benches/benchmarks.rs | 94 + vendor/backtrace/build.rs | 13 + vendor/backtrace/ci/azure-install-rust.yml | 23 + vendor/backtrace/ci/azure-test-all.yml | 49 + .../powerpc-unknown-linux-gnu/Dockerfile | 9 - vendor/backtrace/examples/raw.rs | 22 +- vendor/backtrace/src/backtrace/dbghelp.rs | 210 +- vendor/backtrace/src/backtrace/libunwind.rs | 97 +- vendor/backtrace/src/backtrace/mod.rs | 50 +- vendor/backtrace/src/backtrace/noop.rs | 4 + .../backtrace/src/backtrace/unix_backtrace.rs | 27 +- vendor/backtrace/src/capture.rs | 340 +- vendor/backtrace/src/dbghelp.rs | 318 + vendor/backtrace/src/dylib.rs | 69 - vendor/backtrace/src/lib.rs | 68 +- .../src/symbolize/coresymbolication.rs | 232 +- vendor/backtrace/src/symbolize/dbghelp.rs | 152 +- vendor/backtrace/src/symbolize/dladdr.rs | 114 +- .../backtrace/src/symbolize/dladdr_resolve.rs | 51 + vendor/backtrace/src/symbolize/gimli.rs | 47 +- .../backtrace/src/symbolize/libbacktrace.rs | 443 +- vendor/backtrace/src/symbolize/mod.rs | 171 +- vendor/backtrace/src/symbolize/noop.rs | 11 +- vendor/backtrace/src/types.rs | 58 +- vendor/backtrace/src/windows.rs | 610 + vendor/backtrace/tests/accuracy/auxiliary.rs | 9 + vendor/backtrace/tests/accuracy/main.rs | 94 + vendor/backtrace/tests/long_fn_name.rs | 11 +- vendor/backtrace/tests/skip_inner_frames.rs | 38 +- vendor/backtrace/tests/smoke.rs | 193 +- vendor/bitflags-0.9.1/.cargo-checksum.json | 1 - vendor/bitflags-0.9.1/README.md | 24 - .../bitflags-0.9.1/src/example_generated.rs | 16 - vendor/bitflags-0.9.1/src/lib.rs | 990 - .../tests/conflicting_trait_impls.rs | 20 - vendor/bitflags-0.9.1/tests/external.rs | 21 - .../bitflags-0.9.1/tests/external_no_std.rs | 22 - vendor/bitflags-0.9.1/tests/i128_bitflags.rs | 30 - vendor/cfg-if/.cargo-checksum.json | 2 +- vendor/cfg-if/Cargo.toml | 15 +- vendor/cfg-if/README.md | 2 +- vendor/cfg-if/src/lib.rs | 2 + vendor/compiler_builtins/.cargo-checksum.json | 2 +- vendor/compiler_builtins/Cargo.toml | 2 +- vendor/compiler_builtins/build.rs | 20 +- .../compiler-rt/CMakeLists.txt | 474 - .../compiler-rt/CODE_OWNERS.TXT | 53 - .../compiler_builtins/compiler-rt/CREDITS.TXT | 36 - .../compiler_builtins/compiler-rt/LICENSE.TXT | 91 - .../compiler_builtins/compiler-rt/README.txt | 11 - .../compiler-rt/lib/BlocksRuntime/Block.h | 59 - .../lib/BlocksRuntime/Block_private.h | 179 - .../compiler-rt/lib/BlocksRuntime/data.c | 41 - .../compiler-rt/lib/BlocksRuntime/runtime.c | 700 - .../compiler-rt/lib/CMakeLists.txt | 54 - .../compiler-rt/lib/builtins/CMakeLists.txt | 615 - .../builtins/Darwin-excludes/CMakeLists.txt | 4 - .../lib/builtins/Darwin-excludes/README.TXT | 11 - .../builtins/Darwin-excludes/ios-armv7.txt | 57 - .../builtins/Darwin-excludes/ios-armv7s.txt | 57 - .../lib/builtins/Darwin-excludes/ios.txt | 1 - .../builtins/Darwin-excludes/ios6-armv7.txt | 120 - .../builtins/Darwin-excludes/ios6-armv7s.txt | 120 - .../builtins/Darwin-excludes/ios7-arm64.txt | 16 - .../builtins/Darwin-excludes/iossim-i386.txt | 82 - .../Darwin-excludes/iossim-x86_64.txt | 12 - .../lib/builtins/Darwin-excludes/iossim.txt | 1 - .../lib/builtins/Darwin-excludes/osx-i386.txt | 35 - .../lib/builtins/Darwin-excludes/osx.txt | 7 - .../compiler-rt/lib/builtins/README.txt | 346 - .../compiler-rt/lib/builtins/aarch64/chkstk.S | 34 - .../compiler-rt/lib/builtins/absvdi2.c | 29 - .../compiler-rt/lib/builtins/absvsi2.c | 29 - .../compiler-rt/lib/builtins/absvti2.c | 34 - .../compiler-rt/lib/builtins/adddf3.c | 30 - .../compiler-rt/lib/builtins/addsf3.c | 30 - .../compiler-rt/lib/builtins/addtf3.c | 25 - .../compiler-rt/lib/builtins/addvdi3.c | 36 - .../compiler-rt/lib/builtins/addvsi3.c | 36 - .../compiler-rt/lib/builtins/addvti3.c | 40 - .../lib/builtins/apple_versioning.c | 350 - .../compiler-rt/lib/builtins/arm/adddf3vfp.S | 33 - .../compiler-rt/lib/builtins/arm/addsf3.S | 277 - .../compiler-rt/lib/builtins/arm/addsf3vfp.S | 33 - .../lib/builtins/arm/aeabi_cdcmp.S | 145 - .../builtins/arm/aeabi_cdcmpeq_check_nan.c | 16 - .../lib/builtins/arm/aeabi_cfcmp.S | 140 - .../builtins/arm/aeabi_cfcmpeq_check_nan.c | 16 - .../compiler-rt/lib/builtins/arm/aeabi_dcmp.S | 52 - .../compiler-rt/lib/builtins/arm/aeabi_div0.c | 45 - .../lib/builtins/arm/aeabi_drsub.c | 19 - .../compiler-rt/lib/builtins/arm/aeabi_fcmp.S | 52 - .../lib/builtins/arm/aeabi_frsub.c | 19 - .../lib/builtins/arm/aeabi_idivmod.S | 51 - .../lib/builtins/arm/aeabi_ldivmod.S | 46 - .../lib/builtins/arm/aeabi_memcmp.S | 30 - .../lib/builtins/arm/aeabi_memcpy.S | 30 - .../lib/builtins/arm/aeabi_memmove.S | 29 - .../lib/builtins/arm/aeabi_memset.S | 50 - .../lib/builtins/arm/aeabi_uidivmod.S | 58 - .../lib/builtins/arm/aeabi_uldivmod.S | 46 - .../compiler-rt/lib/builtins/arm/bswapdi2.S | 44 - .../compiler-rt/lib/builtins/arm/bswapsi2.S | 36 - .../compiler-rt/lib/builtins/arm/chkstk.S | 34 - .../compiler-rt/lib/builtins/arm/clzdi2.S | 93 - .../compiler-rt/lib/builtins/arm/clzsi2.S | 73 - .../compiler-rt/lib/builtins/arm/comparesf2.S | 296 - .../compiler-rt/lib/builtins/arm/divdf3vfp.S | 33 - .../compiler-rt/lib/builtins/arm/divmodsi4.S | 71 - .../compiler-rt/lib/builtins/arm/divsf3vfp.S | 33 - .../compiler-rt/lib/builtins/arm/divsi3.S | 82 - .../compiler-rt/lib/builtins/arm/eqdf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/eqsf2vfp.S | 37 - .../lib/builtins/arm/extendsfdf2vfp.S | 33 - .../compiler-rt/lib/builtins/arm/fixdfsivfp.S | 34 - .../compiler-rt/lib/builtins/arm/fixsfsivfp.S | 34 - .../lib/builtins/arm/fixunsdfsivfp.S | 35 - .../lib/builtins/arm/fixunssfsivfp.S | 35 - .../lib/builtins/arm/floatsidfvfp.S | 34 - .../lib/builtins/arm/floatsisfvfp.S | 34 - .../lib/builtins/arm/floatunssidfvfp.S | 34 - .../lib/builtins/arm/floatunssisfvfp.S | 34 - .../compiler-rt/lib/builtins/arm/gedf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/gesf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/gtdf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/gtsf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/ledf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/lesf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/ltdf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/ltsf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/modsi3.S | 60 - .../compiler-rt/lib/builtins/arm/muldf3vfp.S | 33 - .../compiler-rt/lib/builtins/arm/mulsf3vfp.S | 33 - .../compiler-rt/lib/builtins/arm/nedf2vfp.S | 37 - .../compiler-rt/lib/builtins/arm/negdf2vfp.S | 30 - .../compiler-rt/lib/builtins/arm/negsf2vfp.S | 30 - .../compiler-rt/lib/builtins/arm/nesf2vfp.S | 37 - .../builtins/arm/restore_vfp_d8_d15_regs.S | 35 - .../lib/builtins/arm/save_vfp_d8_d15_regs.S | 35 - .../lib/builtins/arm/softfloat-alias.list | 21 - .../compiler-rt/lib/builtins/arm/subdf3vfp.S | 33 - .../compiler-rt/lib/builtins/arm/subsf3vfp.S | 34 - .../compiler-rt/lib/builtins/arm/switch16.S | 46 - .../compiler-rt/lib/builtins/arm/switch32.S | 46 - .../compiler-rt/lib/builtins/arm/switch8.S | 44 - .../compiler-rt/lib/builtins/arm/switchu8.S | 44 - .../compiler-rt/lib/builtins/arm/sync-ops.h | 64 - .../lib/builtins/arm/sync_fetch_and_add_4.S | 23 - .../lib/builtins/arm/sync_fetch_and_add_8.S | 26 - .../lib/builtins/arm/sync_fetch_and_and_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_and_8.S | 26 - .../lib/builtins/arm/sync_fetch_and_max_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_max_8.S | 24 - .../lib/builtins/arm/sync_fetch_and_min_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_min_8.S | 24 - .../lib/builtins/arm/sync_fetch_and_nand_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_nand_8.S | 26 - .../lib/builtins/arm/sync_fetch_and_or_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_or_8.S | 26 - .../lib/builtins/arm/sync_fetch_and_sub_4.S | 23 - .../lib/builtins/arm/sync_fetch_and_sub_8.S | 26 - .../lib/builtins/arm/sync_fetch_and_umax_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_umax_8.S | 24 - .../lib/builtins/arm/sync_fetch_and_umin_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_umin_8.S | 24 - .../lib/builtins/arm/sync_fetch_and_xor_4.S | 22 - .../lib/builtins/arm/sync_fetch_and_xor_8.S | 26 - .../lib/builtins/arm/sync_synchronize.S | 38 - .../lib/builtins/arm/truncdfsf2vfp.S | 33 - .../compiler-rt/lib/builtins/arm/udivmodsi4.S | 180 - .../compiler-rt/lib/builtins/arm/udivsi3.S | 264 - .../compiler-rt/lib/builtins/arm/umodsi3.S | 158 - .../lib/builtins/arm/unorddf2vfp.S | 37 - .../lib/builtins/arm/unordsf2vfp.S | 37 - .../compiler-rt/lib/builtins/ashldi3.c | 45 - .../compiler-rt/lib/builtins/ashlti3.c | 45 - .../compiler-rt/lib/builtins/ashrdi3.c | 46 - .../compiler-rt/lib/builtins/ashrti3.c | 46 - .../compiler-rt/lib/builtins/assembly.h | 204 - .../compiler-rt/lib/builtins/atomic.c | 338 - .../lib/builtins/atomic_flag_clear.c | 27 - .../lib/builtins/atomic_flag_clear_explicit.c | 28 - .../lib/builtins/atomic_flag_test_and_set.c | 27 - .../atomic_flag_test_and_set_explicit.c | 28 - .../lib/builtins/atomic_signal_fence.c | 27 - .../lib/builtins/atomic_thread_fence.c | 27 - .../compiler-rt/lib/builtins/bswapdi2.c | 27 - .../compiler-rt/lib/builtins/bswapsi2.c | 23 - .../compiler-rt/lib/builtins/clear_cache.c | 199 - .../compiler-rt/lib/builtins/clzdi2.c | 40 - .../compiler-rt/lib/builtins/clzsi2.c | 53 - .../compiler-rt/lib/builtins/clzti2.c | 33 - .../compiler-rt/lib/builtins/cmpdi2.c | 51 - .../compiler-rt/lib/builtins/cmpti2.c | 42 - .../compiler-rt/lib/builtins/comparedf2.c | 153 - .../compiler-rt/lib/builtins/comparesf2.c | 153 - .../compiler-rt/lib/builtins/comparetf2.c | 138 - .../compiler-rt/lib/builtins/cpu_model.c | 651 - .../compiler-rt/lib/builtins/ctzdi2.c | 40 - .../compiler-rt/lib/builtins/ctzsi2.c | 57 - .../compiler-rt/lib/builtins/ctzti2.c | 33 - .../compiler-rt/lib/builtins/divdc3.c | 62 - .../compiler-rt/lib/builtins/divdf3.c | 193 - .../compiler-rt/lib/builtins/divdi3.c | 29 - .../compiler-rt/lib/builtins/divmoddi4.c | 25 - .../compiler-rt/lib/builtins/divmodsi4.c | 27 - .../compiler-rt/lib/builtins/divsc3.c | 63 - .../compiler-rt/lib/builtins/divsf3.c | 177 - .../compiler-rt/lib/builtins/divsi3.c | 39 - .../compiler-rt/lib/builtins/divtc3.c | 63 - .../compiler-rt/lib/builtins/divtf3.c | 203 - .../compiler-rt/lib/builtins/divti3.c | 33 - .../compiler-rt/lib/builtins/divxc3.c | 63 - .../compiler-rt/lib/builtins/emutls.c | 405 - .../lib/builtins/enable_execute_stack.c | 72 - .../compiler-rt/lib/builtins/eprintf.c | 35 - .../compiler-rt/lib/builtins/extenddftf2.c | 23 - .../compiler-rt/lib/builtins/extendhfsf2.c | 33 - .../compiler-rt/lib/builtins/extendsfdf2.c | 27 - .../compiler-rt/lib/builtins/extendsftf2.c | 23 - .../compiler-rt/lib/builtins/ffsdi2.c | 33 - .../compiler-rt/lib/builtins/ffssi2.c | 29 - .../compiler-rt/lib/builtins/ffsti2.c | 37 - .../compiler-rt/lib/builtins/fixdfdi.c | 55 - .../compiler-rt/lib/builtins/fixdfsi.c | 30 - .../compiler-rt/lib/builtins/fixdfti.c | 26 - .../compiler-rt/lib/builtins/fixsfdi.c | 55 - .../compiler-rt/lib/builtins/fixsfsi.c | 30 - .../compiler-rt/lib/builtins/fixsfti.c | 26 - .../compiler-rt/lib/builtins/fixtfdi.c | 23 - .../compiler-rt/lib/builtins/fixtfsi.c | 23 - .../compiler-rt/lib/builtins/fixtfti.c | 23 - .../compiler-rt/lib/builtins/fixunsdfdi.c | 52 - .../compiler-rt/lib/builtins/fixunsdfsi.c | 29 - .../compiler-rt/lib/builtins/fixunsdfti.c | 23 - .../compiler-rt/lib/builtins/fixunssfdi.c | 53 - .../compiler-rt/lib/builtins/fixunssfsi.c | 33 - .../compiler-rt/lib/builtins/fixunssfti.c | 26 - .../compiler-rt/lib/builtins/fixunstfdi.c | 22 - .../compiler-rt/lib/builtins/fixunstfsi.c | 22 - .../compiler-rt/lib/builtins/fixunstfti.c | 22 - .../compiler-rt/lib/builtins/fixunsxfdi.c | 46 - .../compiler-rt/lib/builtins/fixunsxfsi.c | 45 - .../compiler-rt/lib/builtins/fixunsxfti.c | 50 - .../compiler-rt/lib/builtins/fixxfdi.c | 48 - .../compiler-rt/lib/builtins/fixxfti.c | 51 - .../compiler-rt/lib/builtins/floatdidf.c | 115 - .../compiler-rt/lib/builtins/floatdisf.c | 88 - .../compiler-rt/lib/builtins/floatditf.c | 50 - .../compiler-rt/lib/builtins/floatdixf.c | 46 - .../compiler-rt/lib/builtins/floatsidf.c | 61 - .../compiler-rt/lib/builtins/floatsisf.c | 67 - .../compiler-rt/lib/builtins/floatsitf.c | 50 - .../compiler-rt/lib/builtins/floattidf.c | 83 - .../compiler-rt/lib/builtins/floattisf.c | 82 - .../compiler-rt/lib/builtins/floattitf.c | 82 - .../compiler-rt/lib/builtins/floattixf.c | 84 - .../compiler-rt/lib/builtins/floatundidf.c | 114 - .../compiler-rt/lib/builtins/floatundisf.c | 85 - .../compiler-rt/lib/builtins/floatunditf.c | 40 - .../compiler-rt/lib/builtins/floatundixf.c | 42 - .../compiler-rt/lib/builtins/floatunsidf.c | 50 - .../compiler-rt/lib/builtins/floatunsisf.c | 58 - .../compiler-rt/lib/builtins/floatunsitf.c | 40 - .../compiler-rt/lib/builtins/floatuntidf.c | 80 - .../compiler-rt/lib/builtins/floatuntisf.c | 79 - .../compiler-rt/lib/builtins/floatuntitf.c | 79 - .../compiler-rt/lib/builtins/floatuntixf.c | 81 - .../compiler-rt/lib/builtins/fp_add_impl.inc | 144 - .../compiler-rt/lib/builtins/fp_extend.h | 89 - .../lib/builtins/fp_extend_impl.inc | 108 - .../lib/builtins/fp_fixint_impl.inc | 41 - .../lib/builtins/fp_fixuint_impl.inc | 39 - .../compiler-rt/lib/builtins/fp_lib.h | 327 - .../compiler-rt/lib/builtins/fp_mul_impl.inc | 116 - .../compiler-rt/lib/builtins/fp_trunc.h | 76 - .../lib/builtins/fp_trunc_impl.inc | 135 - .../lib/builtins/gcc_personality_v0.c | 251 - .../builtins/hexagon/common_entry_exit_abi1.S | 103 - .../builtins/hexagon/common_entry_exit_abi2.S | 268 - .../hexagon/common_entry_exit_legacy.S | 157 - .../lib/builtins/hexagon/dfaddsub.S | 398 - .../compiler-rt/lib/builtins/hexagon/dfdiv.S | 492 - .../compiler-rt/lib/builtins/hexagon/dffma.S | 705 - .../lib/builtins/hexagon/dfminmax.S | 79 - .../compiler-rt/lib/builtins/hexagon/dfmul.S | 418 - .../compiler-rt/lib/builtins/hexagon/dfsqrt.S | 406 - .../compiler-rt/lib/builtins/hexagon/divdi3.S | 85 - .../compiler-rt/lib/builtins/hexagon/divsi3.S | 84 - .../lib/builtins/hexagon/fabs_opt.S | 37 - .../lib/builtins/hexagon/fastmath2_dlib_asm.S | 491 - .../builtins/hexagon/fastmath2_ldlib_asm.S | 345 - .../lib/builtins/hexagon/fastmath_dlib_asm.S | 400 - .../lib/builtins/hexagon/fma_opt.S | 31 - .../lib/builtins/hexagon/fmax_opt.S | 30 - .../lib/builtins/hexagon/fmin_opt.S | 30 - .../hexagon/memcpy_forward_vp4cp4n2.S | 125 - .../builtins/hexagon/memcpy_likely_aligned.S | 64 - .../compiler-rt/lib/builtins/hexagon/moddi3.S | 83 - .../compiler-rt/lib/builtins/hexagon/modsi3.S | 66 - .../lib/builtins/hexagon/sfdiv_opt.S | 66 - .../lib/builtins/hexagon/sfsqrt_opt.S | 82 - .../lib/builtins/hexagon/udivdi3.S | 71 - .../lib/builtins/hexagon/udivmoddi4.S | 71 - .../lib/builtins/hexagon/udivmodsi4.S | 60 - .../lib/builtins/hexagon/udivsi3.S | 56 - .../lib/builtins/hexagon/umoddi3.S | 74 - .../lib/builtins/hexagon/umodsi3.S | 55 - .../compiler-rt/lib/builtins/i386/ashldi3.S | 61 - .../compiler-rt/lib/builtins/i386/ashrdi3.S | 72 - .../compiler-rt/lib/builtins/i386/chkstk.S | 34 - .../compiler-rt/lib/builtins/i386/chkstk2.S | 40 - .../compiler-rt/lib/builtins/i386/divdi3.S | 165 - .../compiler-rt/lib/builtins/i386/floatdidf.S | 42 - .../compiler-rt/lib/builtins/i386/floatdisf.S | 35 - .../compiler-rt/lib/builtins/i386/floatdixf.S | 33 - .../lib/builtins/i386/floatundidf.S | 55 - .../lib/builtins/i386/floatundisf.S | 108 - .../lib/builtins/i386/floatundixf.S | 46 - .../compiler-rt/lib/builtins/i386/lshrdi3.S | 62 - .../compiler-rt/lib/builtins/i386/moddi3.S | 169 - .../compiler-rt/lib/builtins/i386/muldi3.S | 33 - .../compiler-rt/lib/builtins/i386/udivdi3.S | 118 - .../compiler-rt/lib/builtins/i386/umoddi3.S | 129 - .../compiler-rt/lib/builtins/int_endianness.h | 116 - .../compiler-rt/lib/builtins/int_lib.h | 156 - .../compiler-rt/lib/builtins/int_math.h | 109 - .../compiler-rt/lib/builtins/int_types.h | 185 - .../compiler-rt/lib/builtins/int_util.c | 71 - .../compiler-rt/lib/builtins/int_util.h | 33 - .../compiler-rt/lib/builtins/lshrdi3.c | 45 - .../compiler-rt/lib/builtins/lshrti3.c | 45 - .../builtins/macho_embedded/CMakeLists.txt | 4 - .../lib/builtins/macho_embedded/arm.txt | 16 - .../lib/builtins/macho_embedded/common.txt | 92 - .../lib/builtins/macho_embedded/i386.txt | 7 - .../lib/builtins/macho_embedded/thumb2-64.txt | 10 - .../lib/builtins/macho_embedded/thumb2.txt | 14 - .../compiler-rt/lib/builtins/mingw_fixfloat.c | 36 - .../compiler-rt/lib/builtins/moddi3.c | 30 - .../compiler-rt/lib/builtins/modsi3.c | 23 - .../compiler-rt/lib/builtins/modti3.c | 34 - .../compiler-rt/lib/builtins/muldc3.c | 73 - .../compiler-rt/lib/builtins/muldf3.c | 30 - .../compiler-rt/lib/builtins/muldi3.c | 58 - .../compiler-rt/lib/builtins/mulodi4.c | 58 - .../compiler-rt/lib/builtins/mulosi4.c | 58 - .../compiler-rt/lib/builtins/muloti4.c | 62 - .../compiler-rt/lib/builtins/mulsc3.c | 73 - .../compiler-rt/lib/builtins/mulsf3.c | 30 - .../compiler-rt/lib/builtins/multc3.c | 68 - .../compiler-rt/lib/builtins/multf3.c | 25 - .../compiler-rt/lib/builtins/multi3.c | 58 - .../compiler-rt/lib/builtins/mulvdi3.c | 56 - .../compiler-rt/lib/builtins/mulvsi3.c | 56 - .../compiler-rt/lib/builtins/mulvti3.c | 60 - .../compiler-rt/lib/builtins/mulxc3.c | 77 - .../compiler-rt/lib/builtins/negdf2.c | 30 - .../compiler-rt/lib/builtins/negdi2.c | 26 - .../compiler-rt/lib/builtins/negsf2.c | 30 - .../compiler-rt/lib/builtins/negti2.c | 30 - .../compiler-rt/lib/builtins/negvdi2.c | 28 - .../compiler-rt/lib/builtins/negvsi2.c | 28 - .../compiler-rt/lib/builtins/negvti2.c | 32 - .../lib/builtins/os_version_check.c | 226 - .../compiler-rt/lib/builtins/paritydi2.c | 25 - .../compiler-rt/lib/builtins/paritysi2.c | 27 - .../compiler-rt/lib/builtins/parityti2.c | 29 - .../compiler-rt/lib/builtins/popcountdi2.c | 36 - .../compiler-rt/lib/builtins/popcountsi2.c | 33 - .../compiler-rt/lib/builtins/popcountti2.c | 44 - .../compiler-rt/lib/builtins/powidf2.c | 34 - .../compiler-rt/lib/builtins/powisf2.c | 34 - .../compiler-rt/lib/builtins/powitf2.c | 38 - .../compiler-rt/lib/builtins/powixf2.c | 38 - .../compiler-rt/lib/builtins/ppc/DD.h | 45 - .../compiler-rt/lib/builtins/ppc/divtc3.c | 97 - .../compiler-rt/lib/builtins/ppc/fixtfdi.c | 104 - .../compiler-rt/lib/builtins/ppc/fixunstfdi.c | 59 - .../compiler-rt/lib/builtins/ppc/fixunstfti.c | 106 - .../compiler-rt/lib/builtins/ppc/floatditf.c | 36 - .../compiler-rt/lib/builtins/ppc/floattitf.c | 48 - .../lib/builtins/ppc/floatunditf.c | 41 - .../compiler-rt/lib/builtins/ppc/gcc_qadd.c | 76 - .../compiler-rt/lib/builtins/ppc/gcc_qdiv.c | 55 - .../compiler-rt/lib/builtins/ppc/gcc_qmul.c | 53 - .../compiler-rt/lib/builtins/ppc/gcc_qsub.c | 76 - .../compiler-rt/lib/builtins/ppc/multc3.c | 90 - .../compiler-rt/lib/builtins/ppc/restFP.S | 46 - .../compiler-rt/lib/builtins/ppc/saveFP.S | 43 - .../compiler-rt/lib/builtins/riscv/mulsi3.S | 28 - .../compiler-rt/lib/builtins/subdf3.c | 32 - .../compiler-rt/lib/builtins/subsf3.c | 32 - .../compiler-rt/lib/builtins/subtf3.c | 27 - .../compiler-rt/lib/builtins/subvdi3.c | 36 - .../compiler-rt/lib/builtins/subvsi3.c | 36 - .../compiler-rt/lib/builtins/subvti3.c | 40 - .../lib/builtins/trampoline_setup.c | 48 - .../compiler-rt/lib/builtins/truncdfhf2.c | 26 - .../compiler-rt/lib/builtins/truncdfsf2.c | 26 - .../compiler-rt/lib/builtins/truncsfhf2.c | 32 - .../compiler-rt/lib/builtins/trunctfdf2.c | 22 - .../compiler-rt/lib/builtins/trunctfsf2.c | 22 - .../compiler-rt/lib/builtins/ucmpdi2.c | 51 - .../compiler-rt/lib/builtins/ucmpti2.c | 42 - .../compiler-rt/lib/builtins/udivdi3.c | 23 - .../compiler-rt/lib/builtins/udivmoddi4.c | 231 - .../compiler-rt/lib/builtins/udivmodsi4.c | 27 - .../compiler-rt/lib/builtins/udivmodti4.c | 238 - .../compiler-rt/lib/builtins/udivsi3.c | 68 - .../compiler-rt/lib/builtins/udivti3.c | 27 - .../compiler-rt/lib/builtins/umoddi3.c | 25 - .../compiler-rt/lib/builtins/umodsi3.c | 23 - .../compiler-rt/lib/builtins/umodti3.c | 29 - .../lib/builtins/unwind-ehabi-helpers.h | 55 - .../compiler-rt/lib/builtins/x86_64/chkstk.S | 39 - .../compiler-rt/lib/builtins/x86_64/chkstk2.S | 42 - .../lib/builtins/x86_64/floatdidf.c | 16 - .../lib/builtins/x86_64/floatdisf.c | 14 - .../lib/builtins/x86_64/floatdixf.c | 16 - .../lib/builtins/x86_64/floatundidf.S | 52 - .../lib/builtins/x86_64/floatundisf.S | 38 - .../lib/builtins/x86_64/floatundixf.S | 71 - .../compiler-rt/lib/cfi/CMakeLists.txt | 41 - .../compiler-rt/lib/cfi/cfi.cc | 477 - .../compiler-rt/lib/cfi/cfi_blacklist.txt | 17 - .../compiler-rt/lib/safestack/CMakeLists.txt | 19 - .../compiler-rt/lib/safestack/safestack.cc | 318 - .../compiler-rt/lib/stats/CMakeLists.txt | 45 - .../compiler-rt/lib/stats/stats.cc | 137 - .../compiler-rt/lib/stats/stats.h | 43 - .../compiler-rt/lib/stats/stats_client.cc | 84 - .../lib/ubsan_minimal/CMakeLists.txt | 53 - .../lib/ubsan_minimal/ubsan.syms.extra | 1 - .../ubsan_minimal/ubsan_minimal_handlers.cc | 119 - .../utils/generate_netbsd_ioctls.awk | 636 - .../utils/generate_netbsd_syscalls.awk | 2982 --- .../compiler_builtins/examples/intrinsics.rs | 2 +- .../compiler_builtins/libm/src/math/acos.rs | 5 + .../compiler_builtins/libm/src/math/acosf.rs | 5 + .../compiler_builtins/libm/src/math/acosh.rs | 26 + .../compiler_builtins/libm/src/math/acoshf.rs | 25 + .../compiler_builtins/libm/src/math/asin.rs | 5 + .../compiler_builtins/libm/src/math/asinf.rs | 5 + .../compiler_builtins/libm/src/math/asinh.rs | 39 + .../compiler_builtins/libm/src/math/asinhf.rs | 38 + .../compiler_builtins/libm/src/math/atan.rs | 4 + .../compiler_builtins/libm/src/math/atan2.rs | 7 +- .../compiler_builtins/libm/src/math/atan2f.rs | 5 + .../compiler_builtins/libm/src/math/atanf.rs | 4 + .../compiler_builtins/libm/src/math/atanh.rs | 36 + .../compiler_builtins/libm/src/math/atanhf.rs | 36 + .../compiler_builtins/libm/src/math/cbrt.rs | 3 + .../compiler_builtins/libm/src/math/cbrtf.rs | 3 + .../compiler_builtins/libm/src/math/ceil.rs | 3 + .../compiler_builtins/libm/src/math/ceilf.rs | 5 +- .../libm/src/math/copysign.rs | 11 + .../libm/src/math/copysignf.rs | 11 + .../compiler_builtins/libm/src/math/cosh.rs | 5 + .../compiler_builtins/libm/src/math/coshf.rs | 5 + vendor/compiler_builtins/libm/src/math/erf.rs | 317 + .../compiler_builtins/libm/src/math/erff.rs | 229 + vendor/compiler_builtins/libm/src/math/exp.rs | 4 + .../compiler_builtins/libm/src/math/exp10.rs | 21 + .../compiler_builtins/libm/src/math/exp10f.rs | 21 + .../compiler_builtins/libm/src/math/exp2.rs | 12 +- .../compiler_builtins/libm/src/math/exp2f.rs | 4 + .../compiler_builtins/libm/src/math/expf.rs | 4 + .../compiler_builtins/libm/src/math/expm1.rs | 7 + .../compiler_builtins/libm/src/math/expm1f.rs | 7 + .../compiler_builtins/libm/src/math/expo2.rs | 2 +- .../compiler_builtins/libm/src/math/fabs.rs | 3 + .../compiler_builtins/libm/src/math/fabsf.rs | 3 + .../compiler_builtins/libm/src/math/fdim.rs | 8 + .../compiler_builtins/libm/src/math/fdimf.rs | 8 + .../compiler_builtins/libm/src/math/floor.rs | 3 + .../compiler_builtins/libm/src/math/floorf.rs | 3 + vendor/compiler_builtins/libm/src/math/fma.rs | 9 +- .../compiler_builtins/libm/src/math/fmaf.rs | 6 + .../compiler_builtins/libm/src/math/fmax.rs | 13 + .../compiler_builtins/libm/src/math/fmaxf.rs | 13 + .../compiler_builtins/libm/src/math/fmin.rs | 13 + .../compiler_builtins/libm/src/math/fminf.rs | 13 + .../compiler_builtins/libm/src/math/fmod.rs | 4 +- .../compiler_builtins/libm/src/math/fmodf.rs | 4 +- .../compiler_builtins/libm/src/math/frexp.rs | 20 + .../compiler_builtins/libm/src/math/frexpf.rs | 21 + .../compiler_builtins/libm/src/math/ilogb.rs | 31 + .../compiler_builtins/libm/src/math/ilogbf.rs | 31 + vendor/compiler_builtins/libm/src/math/j0.rs | 422 + vendor/compiler_builtins/libm/src/math/j0f.rs | 359 + vendor/compiler_builtins/libm/src/math/j1.rs | 414 + vendor/compiler_builtins/libm/src/math/j1f.rs | 358 + vendor/compiler_builtins/libm/src/math/jn.rs | 343 + vendor/compiler_builtins/libm/src/math/jnf.rs | 259 + .../compiler_builtins/libm/src/math/k_cos.rs | 2 +- .../compiler_builtins/libm/src/math/k_cosf.rs | 2 +- .../libm/src/math/k_expo2f.rs | 2 +- .../compiler_builtins/libm/src/math/k_sin.rs | 2 +- .../compiler_builtins/libm/src/math/k_sinf.rs | 2 +- .../compiler_builtins/libm/src/math/k_tan.rs | 2 +- .../compiler_builtins/libm/src/math/k_tanf.rs | 2 +- .../compiler_builtins/libm/src/math/lgamma.rs | 5 + .../libm/src/math/lgamma_r.rs | 319 + .../libm/src/math/lgammaf.rs | 5 + .../libm/src/math/lgammaf_r.rs | 254 + vendor/compiler_builtins/libm/src/math/mod.rs | 84 + .../compiler_builtins/libm/src/math/modf.rs | 34 + .../compiler_builtins/libm/src/math/modff.rs | 33 + .../libm/src/math/rem_pio2.rs | 24 +- .../libm/src/math/rem_pio2_large.rs | 4 +- .../libm/src/math/rem_pio2f.rs | 2 +- .../compiler_builtins/libm/src/math/remquo.rs | 97 + .../libm/src/math/remquof.rs | 96 + vendor/compiler_builtins/libm/src/math/sin.rs | 7 + .../compiler_builtins/libm/src/math/sincos.rs | 59 + .../libm/src/math/sincosf.rs | 123 + .../compiler_builtins/libm/src/math/tgamma.rs | 207 + .../libm/src/math/tgammaf.rs | 5 + vendor/compiler_builtins/src/math.rs | 4 + vendor/darling/.cargo-checksum.json | 1 + vendor/darling/CHANGELOG.md | 95 + vendor/darling/Cargo.toml | 41 + .../LICENSE-MIT => darling/LICENSE} | 4 +- vendor/darling/README.md | 102 + vendor/darling/examples/automatic_bounds.rs | 78 + vendor/darling/examples/consume_fields.rs | 175 + vendor/darling/examples/fallible_read.rs | 87 + vendor/darling/examples/supports_struct.rs | 62 + vendor/darling/src/lib.rs | 98 + vendor/darling/src/macros_public.rs | 98 + vendor/darling/tests/accrue_errors.rs | 108 + vendor/darling/tests/computed_bound.rs | 46 + vendor/darling/tests/custom_bound.rs | 25 + vendor/darling/tests/defaults.rs | 32 + vendor/darling/tests/enums_newtype.rs | 96 + vendor/darling/tests/enums_struct.rs | 16 + vendor/darling/tests/enums_unit.rs | 16 + vendor/darling/tests/error.rs | 55 + vendor/darling/tests/from_generics.rs | 186 + vendor/darling/tests/from_type_param.rs | 65 + .../darling/tests/from_type_param_default.rs | 59 + vendor/darling/tests/from_variant.rs | 27 + vendor/darling/tests/generics.rs | 27 + vendor/darling/tests/happy_path.rs | 75 + vendor/darling/tests/multiple.rs | 36 + vendor/darling/tests/newtype.rs | 32 + vendor/darling/tests/skip.rs | 52 + vendor/darling/tests/split_declaration.rs | 78 + vendor/darling/tests/suggestions.rs | 34 + vendor/darling/tests/supports.rs | 85 + vendor/darling_core/.cargo-checksum.json | 1 + vendor/darling_core/Cargo.toml | 43 + .../LICENSE | 12 +- vendor/darling_core/src/ast/data.rs | 366 + vendor/darling_core/src/ast/generics.rs | 194 + vendor/darling_core/src/ast/mod.rs | 7 + .../src/codegen/attr_extractor.rs | 110 + .../darling_core/src/codegen/default_expr.rs | 46 + vendor/darling_core/src/codegen/error.rs | 48 + vendor/darling_core/src/codegen/field.rs | 206 + .../src/codegen/from_derive_impl.rs | 146 + vendor/darling_core/src/codegen/from_field.rs | 115 + .../src/codegen/from_meta_impl.rs | 136 + .../src/codegen/from_type_param.rs | 114 + .../src/codegen/from_variant_impl.rs | 118 + vendor/darling_core/src/codegen/mod.rs | 29 + .../src/codegen/outer_from_impl.rs | 60 + vendor/darling_core/src/codegen/trait_impl.rs | 148 + vendor/darling_core/src/codegen/variant.rs | 158 + .../darling_core/src/codegen/variant_data.rs | 88 + vendor/darling_core/src/derive.rs | 54 + vendor/darling_core/src/error/kind.rs | 201 + vendor/darling_core/src/error/mod.rs | 505 + vendor/darling_core/src/from_derive_input.rs | 26 + vendor/darling_core/src/from_field.rs | 38 + vendor/darling_core/src/from_generic_param.rs | 21 + vendor/darling_core/src/from_generics.rs | 27 + vendor/darling_core/src/from_meta.rs | 498 + vendor/darling_core/src/from_type_param.rs | 32 + vendor/darling_core/src/from_variant.rs | 33 + vendor/darling_core/src/lib.rs | 47 + vendor/darling_core/src/macros_private.rs | 12 + vendor/darling_core/src/macros_public.rs | 98 + vendor/darling_core/src/options/core.rs | 160 + .../darling_core/src/options/forward_attrs.rs | 31 + .../darling_core/src/options/from_derive.rs | 101 + vendor/darling_core/src/options/from_field.rs | 79 + vendor/darling_core/src/options/from_meta.rs | 51 + .../src/options/from_type_param.rs | 79 + .../darling_core/src/options/from_variant.rs | 77 + .../darling_core/src/options/input_field.rs | 147 + .../darling_core/src/options/input_variant.rs | 100 + vendor/darling_core/src/options/mod.rs | 154 + vendor/darling_core/src/options/outer_from.rs | 86 + vendor/darling_core/src/options/shape.rs | 260 + vendor/darling_core/src/usage/generics_ext.rs | 24 + vendor/darling_core/src/usage/ident_set.rs | 8 + vendor/darling_core/src/usage/lifetimes.rs | 325 + vendor/darling_core/src/usage/mod.rs | 111 + vendor/darling_core/src/usage/options.rs | 58 + vendor/darling_core/src/usage/type_params.rs | 356 + vendor/darling_core/src/util/ident_list.rs | 101 + vendor/darling_core/src/util/ident_string.rs | 155 + vendor/darling_core/src/util/ignored.rs | 52 + vendor/darling_core/src/util/mod.rs | 112 + vendor/darling_core/src/util/over_ride.rs | 150 + vendor/darling_core/src/util/spanned_value.rs | 104 + vendor/darling_core/src/util/with_original.rs | 35 + vendor/darling_macro/.cargo-checksum.json | 1 + .../Cargo.toml | 32 +- vendor/darling_macro/LICENSE | 21 + vendor/darling_macro/src/lib.rs | 41 + vendor/env_logger/.cargo-checksum.json | 1 + vendor/env_logger/Cargo.toml | 57 + .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 vendor/env_logger/README.md | 144 + .../examples/custom_default_format.rs | 44 + vendor/env_logger/examples/custom_format.rs | 54 + vendor/env_logger/examples/custom_logger.rs | 60 + vendor/env_logger/examples/default.rs | 36 + vendor/env_logger/examples/direct_logger.rs | 40 + vendor/env_logger/src/filter/mod.rs | 579 + vendor/env_logger/src/filter/regex.rs | 29 + vendor/env_logger/src/filter/string.rs | 22 + .../src/fmt/humantime/extern_impl.rs | 84 + vendor/env_logger/src/fmt/humantime/mod.rs | 11 + .../env_logger/src/fmt/humantime/shim_impl.rs | 7 + vendor/env_logger/src/fmt/mod.rs | 356 + vendor/env_logger/src/fmt/writer/atty.rs | 34 + vendor/env_logger/src/fmt/writer/mod.rs | 198 + .../src/fmt/writer/termcolor/extern_impl.rs | 443 + .../src/fmt/writer/termcolor/mod.rs | 12 + .../src/fmt/writer/termcolor/shim_impl.rs | 65 + vendor/env_logger/src/lib.rs | 1110 ++ .../tests/init-twice-retains-filter.rs | 40 + vendor/env_logger/tests/log-in-log.rs | 38 + vendor/env_logger/tests/regexp_filter.rs | 51 + vendor/fnv/.cargo-checksum.json | 1 + vendor/fnv/Cargo.toml | 25 + vendor/{rand-0.4.3 => fnv}/LICENSE-APACHE | 0 vendor/fnv/LICENSE-MIT | 25 + vendor/fnv/README.md | 81 + vendor/fnv/lib.rs | 349 + vendor/fuchsia-cprng/.cargo-checksum.json | 1 + vendor/fuchsia-cprng/AUTHORS | 10 + vendor/fuchsia-cprng/Cargo.toml | 22 + vendor/fuchsia-cprng/LICENSE | 27 + vendor/fuchsia-cprng/PATENTS | 22 + vendor/fuchsia-cprng/src/lib.rs | 57 + vendor/html5ever/.cargo-checksum.json | 2 +- vendor/html5ever/Cargo.toml | 11 +- vendor/html5ever/LICENSE-APACHE | 201 + vendor/html5ever/LICENSE-MIT | 25 + vendor/html5ever/benches/html5ever.rs | 83 + vendor/html5ever/benches/tokenizer.rs | 157 - vendor/html5ever/build.rs | 15 +- vendor/html5ever/examples/arena.rs | 98 +- vendor/html5ever/examples/html2html.rs | 14 +- vendor/html5ever/examples/noop-tokenize.rs | 4 +- .../html5ever/examples/noop-tree-builder.rs | 45 +- vendor/html5ever/examples/print-rcdom.rs | 43 +- .../html5ever/examples/print-tree-actions.rs | 62 +- vendor/html5ever/examples/tokenize.rs | 45 +- vendor/html5ever/macros/match_token.rs | 79 +- vendor/html5ever/src/driver.rs | 63 +- vendor/html5ever/src/lib.rs | 18 +- vendor/html5ever/src/macros.rs | 6 +- vendor/html5ever/src/serialize/mod.rs | 73 +- .../html5ever/src/tokenizer/char_ref/mod.rs | 175 +- vendor/html5ever/src/tokenizer/interface.rs | 10 +- vendor/html5ever/src/tokenizer/mod.rs | 978 +- vendor/html5ever/src/tokenizer/states.rs | 4 +- vendor/html5ever/src/tree_builder/data.rs | 40 +- vendor/html5ever/src/tree_builder/mod.rs | 601 +- vendor/html5ever/src/tree_builder/rules.rs | 9 +- vendor/html5ever/src/tree_builder/tag_sets.rs | 37 +- vendor/html5ever/src/tree_builder/types.rs | 13 +- vendor/html5ever/src/util/str.rs | 12 +- .../tests/foreach_html5lib_test/mod.rs | 17 +- vendor/html5ever/tests/serializer.rs | 158 +- vendor/html5ever/tests/tokenizer.rs | 210 +- vendor/html5ever/tests/tree_builder.rs | 143 +- vendor/ident_case/.cargo-checksum.json | 1 + vendor/ident_case/CHANGELOG.md | 2 + .../{bitflags-0.9.1 => ident_case}/Cargo.toml | 22 +- vendor/ident_case/LICENSE | 19 + vendor/ident_case/README.md | 15 + vendor/ident_case/src/lib.rs | 168 + vendor/indexmap/.cargo-checksum.json | 1 + vendor/indexmap/Cargo.toml | 58 + vendor/indexmap/LICENSE-APACHE | 201 + .../{itertools-0.7.8 => indexmap}/LICENSE-MIT | 2 +- vendor/indexmap/README.rst | 287 + vendor/indexmap/benches/bench.rs | 745 + vendor/indexmap/benches/faststring.rs | 183 + vendor/indexmap/src/equivalent.rs | 27 + vendor/indexmap/src/lib.rs | 79 + vendor/indexmap/src/macros.rs | 122 + vendor/indexmap/src/map.rs | 2050 +++ vendor/indexmap/src/mutable_keys.rs | 71 + vendor/indexmap/src/serde.rs | 123 + vendor/indexmap/src/set.rs | 1180 ++ vendor/indexmap/src/util.rs | 17 + vendor/indexmap/tests/equivalent_trait.rs | 55 + vendor/indexmap/tests/quick.rs | 365 + vendor/indexmap/tests/serde.rs | 59 + vendor/indexmap/tests/tests.rs | 32 + vendor/itertools-0.7.8/.cargo-checksum.json | 1 - vendor/itertools-0.7.8/Cargo.toml | 43 - vendor/itertools-0.7.8/Makefile | 34 - vendor/itertools-0.7.8/README.rst | 490 - vendor/itertools-0.7.8/benches/bench1.rs | 735 - vendor/itertools-0.7.8/benches/extra/mod.rs | 4 - .../benches/extra/zipslices.rs | 189 - vendor/itertools-0.7.8/benches/tree_fold1.rs | 126 - .../benches/tuple_combinations.rs | 97 - vendor/itertools-0.7.8/benches/tuples.rs | 190 - vendor/itertools-0.7.8/bors.toml | 3 - vendor/itertools-0.7.8/custom.css | 29 - vendor/itertools-0.7.8/examples/iris.data | 150 - vendor/itertools-0.7.8/examples/iris.rs | 141 - vendor/itertools-0.7.8/src/adaptors/mod.rs | 1293 -- .../src/adaptors/multi_product.rs | 220 - vendor/itertools-0.7.8/src/combinations.rs | 165 - vendor/itertools-0.7.8/src/concat_impl.rs | 22 - .../itertools-0.7.8/src/cons_tuples_impl.rs | 68 - vendor/itertools-0.7.8/src/diff.rs | 61 - vendor/itertools-0.7.8/src/either_or_both.rs | 10 - vendor/itertools-0.7.8/src/format.rs | 113 - vendor/itertools-0.7.8/src/free.rs | 231 - vendor/itertools-0.7.8/src/group_map.rs | 22 - vendor/itertools-0.7.8/src/groupbylazy.rs | 571 - vendor/itertools-0.7.8/src/impl_macros.rs | 14 - vendor/itertools-0.7.8/src/intersperse.rs | 60 - vendor/itertools-0.7.8/src/kmerge_impl.rs | 256 - vendor/itertools-0.7.8/src/lib.rs | 2121 --- vendor/itertools-0.7.8/src/merge_join.rs | 87 - vendor/itertools-0.7.8/src/minmax.rs | 114 - vendor/itertools-0.7.8/src/multipeek_impl.rs | 104 - vendor/itertools-0.7.8/src/pad_tail.rs | 83 - .../itertools-0.7.8/src/peeking_take_while.rs | 149 - .../src/process_results_impl.rs | 81 - vendor/itertools-0.7.8/src/put_back_n_impl.rs | 63 - vendor/itertools-0.7.8/src/rciter_impl.rs | 98 - vendor/itertools-0.7.8/src/repeatn.rs | 54 - vendor/itertools-0.7.8/src/size_hint.rs | 104 - vendor/itertools-0.7.8/src/sources.rs | 187 - vendor/itertools-0.7.8/src/tee.rs | 78 - vendor/itertools-0.7.8/src/tuple_impl.rs | 266 - vendor/itertools-0.7.8/src/unique_impl.rs | 134 - vendor/itertools-0.7.8/src/with_position.rs | 90 - vendor/itertools-0.7.8/src/zip_eq_impl.rs | 60 - vendor/itertools-0.7.8/src/zip_longest.rs | 78 - vendor/itertools-0.7.8/src/ziptuple.rs | 111 - vendor/itertools-0.7.8/tests/merge_join.rs | 110 - .../tests/peeking_take_while.rs | 53 - vendor/itertools-0.7.8/tests/quick.rs | 1019 -- vendor/itertools-0.7.8/tests/test_core.rs | 240 - vendor/itertools-0.7.8/tests/test_std.rs | 749 - vendor/itertools-0.7.8/tests/tuples.rs | 88 - vendor/itertools-0.7.8/tests/zip.rs | 65 - vendor/itoa/.cargo-checksum.json | 2 +- vendor/itoa/Cargo.toml | 4 +- vendor/itoa/README.md | 111 +- vendor/itoa/benches/bench.rs | 1 - vendor/itoa/src/lib.rs | 69 +- vendor/itoa/src/udiv128.rs | 32 +- vendor/itoa/tests/test.rs | 1 - vendor/markup5ever/.cargo-checksum.json | 2 +- vendor/markup5ever/Cargo.toml | 7 +- vendor/markup5ever/LICENSE-APACHE | 201 + vendor/markup5ever/LICENSE-MIT | 25 + vendor/markup5ever/build.rs | 73 +- vendor/markup5ever/data/mod.rs | 40 +- vendor/markup5ever/interface/mod.rs | 255 +- vendor/markup5ever/interface/tree_builder.rs | 130 +- vendor/markup5ever/lib.rs | 83 +- vendor/markup5ever/local_names.txt | 5 + vendor/markup5ever/rcdom.rs | 340 +- vendor/markup5ever/serialize.rs | 10 +- vendor/markup5ever/util/buffer_queue.rs | 87 +- vendor/markup5ever/util/smallcharset.rs | 5 +- vendor/mdbook/.cargo-checksum.json | 2 +- vendor/mdbook/CHANGELOG.md | 190 + vendor/mdbook/Cargo.toml | 30 +- vendor/mdbook/README.md | 14 +- vendor/mdbook/appveyor.yml | 10 +- vendor/mdbook/examples/de-emphasize.rs | 80 - vendor/mdbook/examples/nop-preprocessor.rs | 14 +- vendor/mdbook/src/book/book.rs | 21 +- vendor/mdbook/src/book/init.rs | 29 +- vendor/mdbook/src/book/mod.rs | 114 +- vendor/mdbook/src/book/summary.rs | 19 +- vendor/mdbook/src/cmd/build.rs | 8 +- vendor/mdbook/src/cmd/clean.rs | 7 +- vendor/mdbook/src/cmd/init.rs | 5 +- vendor/mdbook/src/cmd/serve.rs | 18 +- vendor/mdbook/src/cmd/test.rs | 4 +- vendor/mdbook/src/cmd/watch.rs | 56 +- vendor/mdbook/src/config.rs | 43 +- vendor/mdbook/src/lib.rs | 47 +- vendor/mdbook/src/main.rs | 15 +- vendor/mdbook/src/preprocess/cmd.rs | 7 +- vendor/mdbook/src/preprocess/index.rs | 12 +- vendor/mdbook/src/preprocess/links.rs | 38 +- vendor/mdbook/src/preprocess/mod.rs | 8 +- .../renderer/html_handlebars/hbs_renderer.rs | 76 +- .../html_handlebars/helpers/navigation.rs | 127 +- .../renderer/html_handlebars/helpers/theme.rs | 15 +- .../renderer/html_handlebars/helpers/toc.rs | 20 +- .../src/renderer/html_handlebars/search.rs | 40 +- vendor/mdbook/src/renderer/mod.rs | 9 +- vendor/mdbook/src/theme/ayu-highlight.css | 8 + vendor/mdbook/src/theme/book.js | 28 +- vendor/mdbook/src/theme/css/chrome.css | 53 +- vendor/mdbook/src/theme/css/general.css | 13 +- vendor/mdbook/src/theme/index.hbs | 13 +- vendor/mdbook/src/theme/mod.rs | 48 +- vendor/mdbook/src/theme/searcher/mod.rs | 6 +- vendor/mdbook/src/theme/tomorrow-night.css | 8 + vendor/mdbook/src/utils/fs.rs | 56 +- vendor/mdbook/src/utils/mod.rs | 89 +- ...te_backends.rs => alternative_backends.rs} | 5 +- vendor/mdbook/tests/build_process.rs | 6 +- vendor/mdbook/tests/custom_preprocessors.rs | 8 +- vendor/mdbook/tests/dummy_book/mod.rs | 18 +- vendor/mdbook/tests/dummy_book/src/SUMMARY.md | 1 + .../tests/dummy_book/src/first/markdown.md | 29 + .../tests/dummy_book/src/first/nested-test.rs | 1 + .../tests/dummy_book/src/first/nested.md | 4 + .../tests/dummy_book/src/second/nested.md | 6 +- vendor/mdbook/tests/init.rs | 35 +- .../tests/parse_existing_summary_files.rs | 4 - vendor/mdbook/tests/rendered_output.rs | 92 +- vendor/mdbook/tests/searchindex_fixture.json | 1429 +- vendor/mdbook/tests/testing.rs | 4 +- .../.cargo-checksum.json | 2 +- vendor/new_debug_unreachable/Cargo.toml | 4 +- vendor/new_debug_unreachable/README.md | 7 + vendor/new_debug_unreachable/src/lib.rs | 9 +- vendor/proc-macro2/.cargo-checksum.json | 2 +- vendor/proc-macro2/Cargo.toml | 7 +- vendor/proc-macro2/README.md | 76 +- vendor/proc-macro2/build.rs | 116 +- .../src/{stable.rs => fallback.rs} | 133 +- vendor/proc-macro2/src/lib.rs | 180 +- vendor/proc-macro2/src/strnom.rs | 8 +- .../src/{unstable.rs => wrapper.rs} | 446 +- vendor/proc-macro2/tests/test.rs | 88 +- .../pulldown-cmark-0.1.2/.cargo-checksum.json | 1 - vendor/pulldown-cmark-0.1.2/CONTRIBUTING.md | 24 - vendor/pulldown-cmark-0.1.2/README.md | 124 - vendor/pulldown-cmark-0.1.2/build.rs | 152 - .../pulldown-cmark-0.1.2/specs/footnotes.txt | 153 - vendor/pulldown-cmark-0.1.2/specs/table.txt | 214 - vendor/pulldown-cmark-0.1.2/src/entities.rs | 4284 ----- vendor/pulldown-cmark-0.1.2/src/escape.rs | 120 - vendor/pulldown-cmark-0.1.2/src/html.rs | 284 - vendor/pulldown-cmark-0.1.2/src/lib.rs | 42 - vendor/pulldown-cmark-0.1.2/src/main.rs | 258 - vendor/pulldown-cmark-0.1.2/src/parse.rs | 1756 -- vendor/pulldown-cmark-0.1.2/src/passes.rs | 113 - vendor/pulldown-cmark-0.1.2/src/puncttable.rs | 348 - vendor/pulldown-cmark-0.1.2/src/scanners.rs | 702 - vendor/pulldown-cmark-0.1.2/src/utils.rs | 53 - vendor/pulldown-cmark-0.1.2/tests/errors.rs | 38 - .../pulldown-cmark-0.1.2/tests/footnotes.rs | 254 - vendor/pulldown-cmark-0.1.2/tests/html.rs | 240 - vendor/pulldown-cmark-0.1.2/tests/spec.rs | 14997 ---------------- vendor/pulldown-cmark-0.1.2/tests/table.rs | 368 - .../third_party/CommonMark/LICENSE | 105 - .../third_party/CommonMark/README.google | 12 - .../third_party/CommonMark/spec.txt | 9414 ---------- .../pulldown-cmark-0.1.2/tools/mk_entities.py | 72 - .../tools/mk_puncttable.py | 130 - vendor/punycode/.cargo-checksum.json | 1 + vendor/punycode/Cargo.toml | 15 + vendor/punycode/LICENSE.md | 24 + vendor/punycode/src/bin/test_decode.rs | 14 + vendor/punycode/src/bin/test_encode.rs | 11 + vendor/punycode/src/lib.rs | 376 + vendor/quote/.cargo-checksum.json | 2 +- vendor/quote/Cargo.toml | 4 +- vendor/quote/README.md | 114 +- vendor/quote/src/ext.rs | 59 +- vendor/quote/src/lib.rs | 363 +- vendor/quote/src/runtime.rs | 119 + vendor/quote/src/to_tokens.rs | 16 +- .../.cargo-checksum.json | 2 +- .../{rand-0.4.3 => rand-0.4.6}/CHANGELOG.md | 8 + vendor/{rand-0.4.3 => rand-0.4.6}/Cargo.toml | 12 +- vendor/rand-0.4.6/LICENSE-APACHE | 201 + vendor/{rand-0.4.3 => rand-0.4.6}/LICENSE-MIT | 0 vendor/{rand-0.4.3 => rand-0.4.6}/README.md | 0 .../{rand-0.4.3 => rand-0.4.6}/appveyor.yml | 0 .../benches/bench.rs | 0 .../benches/distributions/exponential.rs | 0 .../benches/distributions/gamma.rs | 0 .../benches/distributions/mod.rs | 0 .../benches/distributions/normal.rs | 0 .../benches/generators.rs | 0 .../benches/misc.rs | 0 .../src/distributions/exponential.rs | 0 .../src/distributions/gamma.rs | 0 .../src/distributions/mod.rs | 0 .../src/distributions/normal.rs | 0 .../src/distributions/range.rs | 0 .../src/distributions/ziggurat_tables.rs | 0 .../{rand-0.4.3 => rand-0.4.6}/src/jitter.rs | 0 vendor/{rand-0.4.3 => rand-0.4.6}/src/lib.rs | 6 + vendor/{rand-0.4.3 => rand-0.4.6}/src/os.rs | 61 +- .../src/prng/chacha.rs | 0 .../src/prng/isaac.rs | 0 .../src/prng/isaac64.rs | 0 .../src/prng/mod.rs | 0 .../src/prng/xorshift.rs | 0 .../src/rand_impls.rs | 0 vendor/{rand-0.4.3 => rand-0.4.6}/src/read.rs | 0 .../src/reseeding.rs | 0 vendor/{rand-0.4.3 => rand-0.4.6}/src/seq.rs | 0 .../utils/ziggurat_tables.py | 0 .../.cargo-checksum.json | 0 .../CHANGELOG.md | 0 .../{rand_core => rand_core-0.3.0}/COPYRIGHT | 0 .../{rand_core => rand_core-0.3.0}/Cargo.toml | 0 .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 .../{rand_core => rand_core-0.3.0}/README.md | 0 .../src/block.rs | 0 .../src/error.rs | 0 .../src/impls.rs | 0 .../{rand_core => rand_core-0.3.0}/src/le.rs | 0 .../{rand_core => rand_core-0.3.0}/src/lib.rs | 0 vendor/rayon-core/.cargo-checksum.json | 2 +- vendor/rayon-core/Cargo.toml | 30 +- vendor/rayon-core/src/compile_fail/mod.rs | 8 + .../src/compile_fail/quicksort_race1.rs | 28 + .../src/compile_fail/quicksort_race2.rs | 28 + .../src/compile_fail/quicksort_race3.rs | 28 + .../rayon-core/src/compile_fail/rc_return.rs | 21 + .../rayon-core/src/compile_fail/rc_upvar.rs | 11 + .../src/compile_fail/scope_join_bad.rs | 24 + vendor/rayon-core/src/join/mod.rs | 2 +- vendor/rayon-core/src/join/test.rs | 15 +- vendor/rayon-core/src/lib.rs | 7 +- vendor/rayon-core/src/registry.rs | 64 +- vendor/rayon-core/src/scope/test.rs | 11 +- vendor/rayon-core/tests/double_init_fail.rs | 12 + vendor/rayon-core/tests/init_zero_threads.rs | 11 + vendor/rayon-core/tests/scope_join.rs | 47 + vendor/rayon-core/tests/simple_panic.rs | 9 + .../rayon-core/tests/stack_overflow_crash.rs | 59 + vendor/rdrand/.cargo-checksum.json | 1 + vendor/rdrand/Cargo.toml | 28 + vendor/rdrand/LICENSE | 12 + vendor/rdrand/README.mkd | 8 + vendor/rdrand/appveyor.yml | 27 + vendor/rdrand/benches/rdrand.rs | 49 + vendor/rdrand/benches/rdseed.rs | 49 + vendor/rdrand/benches/std.rs | 31 + vendor/rdrand/src/changelog.rs | 25 + vendor/rdrand/src/lib.rs | 472 + vendor/rustc-demangle/.cargo-checksum.json | 2 +- vendor/rustc-demangle/Cargo.toml | 4 +- vendor/rustc-demangle/src/legacy.rs | 370 + vendor/rustc-demangle/src/lib.rs | 220 +- vendor/rustc-demangle/src/v0.rs | 1067 ++ vendor/serde/.cargo-checksum.json | 2 +- vendor/serde/Cargo.toml | 8 +- vendor/serde/README.md | 36 +- vendor/serde/build.rs | 15 + vendor/serde/crates-io.md | 6 +- vendor/serde/src/de/ignored_any.rs | 4 +- vendor/serde/src/de/impls.rs | 190 +- vendor/serde/src/de/mod.rs | 77 +- vendor/serde/src/de/value.rs | 132 +- vendor/serde/src/export.rs | 2 +- vendor/serde/src/integer128.rs | 16 +- vendor/serde/src/lib.rs | 113 +- vendor/serde/src/macros.rs | 24 +- vendor/serde/src/private/de.rs | 2 +- vendor/serde/src/ser/impls.rs | 47 +- vendor/serde/src/ser/impossible.rs | 9 +- vendor/serde/src/ser/mod.rs | 224 +- vendor/smallvec/.cargo-checksum.json | 2 +- vendor/smallvec/Cargo.toml | 7 +- vendor/smallvec/lib.rs | 93 +- vendor/syn/.cargo-checksum.json | 2 +- vendor/syn/Cargo.toml | 25 +- vendor/syn/LICENSE-MIT | 2 - vendor/syn/README.md | 33 +- vendor/syn/build.rs | 72 + vendor/syn/src/attr.rs | 36 +- vendor/syn/src/buffer.rs | 33 +- vendor/syn/src/custom_keyword.rs | 252 + vendor/syn/src/custom_punctuation.rs | 309 + vendor/syn/src/data.rs | 8 - vendor/syn/src/derive.rs | 8 - vendor/syn/src/error.rs | 34 +- vendor/syn/src/expr.rs | 373 +- vendor/syn/src/ext.rs | 106 +- vendor/syn/src/file.rs | 12 +- vendor/syn/src/gen/fold.rs | 682 +- vendor/syn/src/gen/visit.rs | 501 +- vendor/syn/src/gen/visit_mut.rs | 503 +- vendor/syn/src/gen_helper.rs | 8 - vendor/syn/src/generics.rs | 33 +- vendor/syn/src/group.rs | 39 +- vendor/syn/src/ident.rs | 18 +- vendor/syn/src/item.rs | 203 +- vendor/syn/src/keyword.rs | 254 - vendor/syn/src/lib.rs | 86 +- vendor/syn/src/lifetime.rs | 13 +- vendor/syn/src/lit.rs | 65 +- vendor/syn/src/lookahead.rs | 23 +- vendor/syn/src/mac.rs | 8 - vendor/syn/src/macros.rs | 8 - vendor/syn/src/op.rs | 8 - vendor/syn/src/parse.rs | 192 +- vendor/syn/src/parse_macro_input.rs | 9 +- vendor/syn/src/parse_quote.rs | 23 +- vendor/syn/src/path.rs | 35 +- vendor/syn/src/punctuated.rs | 91 +- vendor/syn/src/sealed.rs | 4 + vendor/syn/src/spanned.rs | 18 +- vendor/syn/src/synom.rs | 0 vendor/syn/src/thread.rs | 2 + vendor/syn/src/token.rs | 102 +- vendor/syn/src/tt.rs | 8 - vendor/syn/src/ty.rs | 10 +- vendor/synstructure/.cargo-checksum.json | 2 +- vendor/synstructure/Cargo.toml | 4 +- vendor/synstructure/src/lib.rs | 208 +- vendor/synstructure/src/macros.rs | 60 +- vendor/toml-query/.cargo-checksum.json | 2 +- vendor/toml-query/CHANGELOG.md | 13 +- vendor/toml-query/Cargo.toml | 17 +- vendor/toml-query/README.md | 10 - vendor/toml-query/src/delete.rs | 108 +- vendor/toml-query/src/error.rs | 161 +- vendor/toml-query/src/insert.rs | 26 +- vendor/toml-query/src/lib.rs | 8 +- vendor/toml-query/src/read.rs | 83 +- .../src/resolver/mut_creating_resolver.rs | 41 +- .../toml-query/src/resolver/mut_resolver.rs | 61 +- .../src/resolver/non_mut_resolver.rs | 56 +- vendor/toml-query/src/set.rs | 53 +- vendor/toml-query/src/tokenizer.rs | 40 +- vendor/toml-query/src/value.rs | 10 +- vendor/toml-query_derive/.cargo-checksum.json | 1 + vendor/toml-query_derive/Cargo.toml | 34 + vendor/toml-query_derive/src/lib.rs | 54 + vendor/toml/.cargo-checksum.json | 1 + vendor/toml/Cargo.toml | 42 + vendor/toml/LICENSE-APACHE | 201 + vendor/toml/LICENSE-MIT | 25 + vendor/toml/README.md | 40 + vendor/toml/examples/decode.rs | 53 + vendor/toml/examples/enum_external.rs | 44 + vendor/toml/examples/toml2json.rs | 47 + vendor/toml/src/datetime.rs | 429 + vendor/toml/src/de.rs | 1991 ++ vendor/toml/src/lib.rs | 170 + vendor/toml/src/macros.rs | 462 + vendor/toml/src/map.rs | 595 + vendor/toml/src/ser.rs | 1870 ++ vendor/toml/src/spanned.rs | 141 + vendor/toml/src/tokens.rs | 737 + vendor/toml/src/value.rs | 1089 ++ .../toml/tests/enum_external_deserialize.rs | 238 + vendor/unreachable/.cargo-checksum.json | 1 - vendor/unreachable/Cargo.toml | 13 - vendor/unreachable/README.md | 35 - vendor/unreachable/src/lib.rs | 77 - vendor/void/.cargo-checksum.json | 1 - vendor/void/Cargo.toml | 15 - vendor/void/README.md | 39 - vendor/void/src/lib.rs | 121 - version | 2 +- 4408 files changed, 132406 insertions(+), 141302 deletions(-) create mode 100644 src/bootstrap/builder/tests.rs create mode 100644 src/ci/awscli-requirements.txt create mode 100644 src/ci/azure-pipelines/auto.yml create mode 100644 src/ci/azure-pipelines/master.yml create mode 100644 src/ci/azure-pipelines/pr.yml create mode 100644 src/ci/azure-pipelines/steps/install-clang.yml create mode 100644 src/ci/azure-pipelines/steps/install-sccache.yml create mode 100644 src/ci/azure-pipelines/steps/install-windows-build-deps.yml create mode 100644 src/ci/azure-pipelines/steps/run.yml create mode 100644 src/ci/azure-pipelines/try.yml create mode 100644 src/ci/cpu-usage-over-time.py delete mode 100644 src/doc/book/nostarch/appendices-d-and-e.md delete mode 100644 src/doc/book/nostarch/appendix-a-new-section.md delete mode 100644 src/doc/book/nostarch/chapter11-using-result-in-tests.md delete mode 100644 src/doc/book/nostarch/chapter12-error-message-updates.md delete mode 100644 src/doc/book/nostarch/chapter15-code-updates.md delete mode 100644 src/doc/book/nostarch/chapter15-error-message-updates.md delete mode 100644 src/doc/book/nostarch/chapter18-destructuring-nested-structs-and-enums.md delete mode 100644 src/doc/book/nostarch/chapter19-new-function-pointer-text.md delete mode 100644 src/doc/book/nostarch/chapter19.md create mode 100755 src/doc/book/tools/megadiff.sh create mode 100644 src/doc/rustc-guide/src/appendix/bibliography.md create mode 100644 src/doc/rustc-guide/src/borrow_check/region_inference/closure_constraints.md create mode 100644 src/doc/rustc-guide/src/borrow_check/region_inference/constraint_propagation.md create mode 100644 src/doc/rustc-guide/src/borrow_check/region_inference/error_reporting.md create mode 100644 src/doc/rustc-guide/src/borrow_check/region_inference/lifetime_parameters.md create mode 100644 src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md create mode 100644 src/doc/rustc-guide/src/borrow_check/region_inference/placeholders_and_universes.md create mode 100644 src/doc/rustc-guide/src/closure.md create mode 100644 src/doc/rustc-guide/src/debugging-support-in-rustc.md rename src/doc/rustc-guide/src/{diag.md => diagnostics.md} (99%) rename src/doc/rustc-guide/src/{diag => diagnostics}/json-format.md (100%) create mode 100644 src/doc/rustc-guide/src/img/rustc_stages.svg create mode 100644 src/doc/rustc-guide/src/profile-guided-optimization.md create mode 100644 src/doc/rustc-guide/triagebot.toml create mode 100644 src/doc/rustc/src/profile-guided-optimization.md create mode 100644 src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md create mode 100644 src/doc/unstable-book/src/language-features/member-constraints.md delete mode 100644 src/doc/unstable-book/src/language-features/repr-align-enum.md create mode 100644 src/doc/unstable-book/src/language-features/transparent-enums.md create mode 100644 src/doc/unstable-book/src/language-features/transparent-unions.md delete mode 100644 src/doc/unstable-book/src/language-features/type-alias-enum-variants.md delete mode 100644 src/doc/unstable-book/src/library-features/borrow-state.md delete mode 100644 src/doc/unstable-book/src/library-features/fnbox.md create mode 100755 src/etc/cpu-usage-over-time-plot.sh rename src/liballoc/{boxed_test.rs => tests.rs} (100%) create mode 100644 src/libarena/tests.rs delete mode 100644 src/libcore/mem.rs create mode 100644 src/libcore/mem/manually_drop.rs create mode 100644 src/libcore/mem/maybe_uninit.rs create mode 100644 src/libcore/mem/mod.rs rename src/libcore/{ptr.rs => ptr/mod.rs} (87%) create mode 100644 src/libcore/ptr/non_null.rs create mode 100644 src/libcore/ptr/unique.rs create mode 100644 src/libfmt_macros/tests.rs create mode 100644 src/libgraphviz/tests.rs delete mode 100644 src/libpanic_unwind/macros.rs create mode 100644 src/librustc/hir/upvars.rs create mode 100644 src/librustc/session/config/tests.rs create mode 100644 src/librustc/ty/print/obsolete.rs create mode 100644 src/librustc_codegen_ssa/back/rpath/tests.rs create mode 100644 src/librustc_codegen_utils/symbol_names/legacy.rs create mode 100644 src/librustc_codegen_utils/symbol_names/v0.rs create mode 100644 src/librustc_data_structures/binary_search_util/mod.rs create mode 100644 src/librustc_data_structures/binary_search_util/test.rs create mode 100644 src/librustc_data_structures/graph/vec_graph/mod.rs create mode 100644 src/librustc_data_structures/graph/vec_graph/test.rs create mode 100644 src/librustc_data_structures/owning_ref/tests.rs create mode 100644 src/librustc_data_structures/sorted_map/tests.rs create mode 100644 src/librustc_errors/annotate_snippet_emitter_writer.rs create mode 100644 src/librustc_lint/nonstandard_style/tests.rs create mode 100644 src/librustc_metadata/dynamic_lib/tests.rs delete mode 100644 src/librustc_metadata/index_builder.rs delete mode 100644 src/librustc_metadata/isolated_encoder.rs create mode 100644 src/librustc_mir/borrow_check/conflict_errors.rs create mode 100644 src/librustc_mir/borrow_check/nll/member_constraints.rs create mode 100644 src/librustc_mir/interpret/intern.rs create mode 100644 src/librustc_mir/interpret/intrinsics/type_name.rs create mode 100644 src/librustc_mir/util/aggregate.rs create mode 100644 src/librustc_typeck/check/expr.rs create mode 100644 src/librustdoc/docfs.rs create mode 100644 src/librustdoc/html/markdown/tests.rs create mode 100644 src/librustdoc/html/toc/tests.rs create mode 100644 src/librustdoc/test/tests.rs create mode 100644 src/libserialize/hex/tests.rs create mode 100644 src/libserialize/json/tests.rs delete mode 100644 src/libstd/sys/cloudabi/backtrace.rs delete mode 100644 src/libstd/sys/redox/backtrace/mod.rs delete mode 100644 src/libstd/sys/redox/backtrace/printing.rs delete mode 100644 src/libstd/sys/redox/backtrace/tracing.rs delete mode 100644 src/libstd/sys/sgx/backtrace.rs delete mode 100644 src/libstd/sys/unix/backtrace/mod.rs delete mode 100644 src/libstd/sys/unix/backtrace/printing/dladdr.rs delete mode 100644 src/libstd/sys/unix/backtrace/printing/mod.rs delete mode 100644 src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs delete mode 100644 src/libstd/sys/unix/backtrace/tracing/gcc_s.rs delete mode 100644 src/libstd/sys/unix/backtrace/tracing/mod.rs delete mode 100644 src/libstd/sys/wasi/backtrace.rs delete mode 100644 src/libstd/sys/wasm/backtrace.rs delete mode 100644 src/libstd/sys/windows/backtrace/backtrace_gnu.rs delete mode 100644 src/libstd/sys/windows/backtrace/mod.rs delete mode 100644 src/libstd/sys/windows/backtrace/printing/mod.rs delete mode 100644 src/libstd/sys/windows/backtrace/printing/msvc.rs delete mode 100644 src/libstd/sys/windows/dynamic_lib.rs delete mode 100644 src/libstd/sys_common/gnu/libbacktrace.rs delete mode 100644 src/libstd/sys_common/gnu/mod.rs create mode 100644 src/libsyntax_ext/format_foreign/printf/tests.rs create mode 100644 src/libsyntax_ext/format_foreign/shell/tests.rs create mode 100644 src/libtest/stats/tests.rs create mode 100644 src/libtest/tests.rs delete mode 100644 src/libunwind/macros.rs create mode 100644 src/test/codegen/c-variadic-copy.rs rename src/test/codegen/{ => intrinsics}/exact_div.rs (87%) rename src/test/codegen/{ => intrinsics}/likely.rs (100%) rename src/test/codegen/{ => intrinsics}/move-val-init.rs (100%) rename src/test/codegen/{ => intrinsics}/nontemporal.rs (100%) rename src/test/codegen/{ => intrinsics}/prefetch.rs (100%) create mode 100644 src/test/codegen/intrinsics/unchecked_math.rs create mode 100644 src/test/codegen/slice-iter-len-eq-zero.rs create mode 100644 src/test/incremental/issue-61530.rs create mode 100644 src/test/mir-opt/byte_slice.rs create mode 100644 src/test/mir-opt/const_prop/indirect.rs create mode 100644 src/test/mir-opt/const_prop/ref_deref.rs create mode 100644 src/test/mir-opt/const_prop/reify_fn_ptr.rs create mode 100644 src/test/mir-opt/generator-storage-dead-unwind.rs create mode 100644 src/test/mir-opt/match-arm-scopes.rs create mode 100644 src/test/mir-opt/simple-match.rs create mode 100644 src/test/mir-opt/while-storage.rs create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs delete mode 100644 src/test/run-pass-fulldeps/auxiliary/custom-derive-partial-eq.rs delete mode 100644 src/test/run-pass-fulldeps/auxiliary/custom-derive-plugin-attr.rs delete mode 100644 src/test/run-pass-fulldeps/auxiliary/custom-derive-plugin.rs delete mode 100644 src/test/run-pass-fulldeps/custom-derive-partial-eq.rs delete mode 100644 src/test/run-pass-fulldeps/derive-totalsum-attr.rs delete mode 100644 src/test/run-pass-fulldeps/derive-totalsum.rs delete mode 100644 src/test/run-pass-fulldeps/issue-40663.rs create mode 100644 src/test/run-pass/abi/issues/issue-62350-sysv-neg-reg-counts.rs create mode 100644 src/test/run-pass/async-await/async-fn-size-moved-locals.rs create mode 100644 src/test/run-pass/async-await/async-fn-size.rs create mode 100644 src/test/run-pass/async-await/issue-60709.rs delete mode 100644 src/test/run-pass/attr-before-view-item.rs delete mode 100644 src/test/run-pass/attr-before-view-item2.rs delete mode 100644 src/test/run-pass/attr-mix-new.rs delete mode 100644 src/test/run-pass/auxiliary/allocator-dummy.rs create mode 100644 src/test/run-pass/borrowck/issue-62007-assign-box.rs create mode 100644 src/test/run-pass/borrowck/issue-62007-assign-field.rs delete mode 100644 src/test/run-pass/compiletest-skip-codegen.rs delete mode 100644 src/test/run-pass/const-int-rotate.rs delete mode 100644 src/test/run-pass/const-int-sign.rs rename src/test/run-pass/{ctfe => consts}/assoc-const.rs (100%) rename src/test/run-pass/{ctfe => consts}/bswap-const.rs (100%) rename src/test/run-pass/{ctfe => consts}/chained-constants-stackoverflow.rs (100%) rename src/test/run-pass/{ctfe => consts}/const-block-non-item-statement-3.rs (100%) rename src/test/run-pass/{ctfe => consts}/const-block-non-item-statement.rs (100%) create mode 100644 src/test/run-pass/consts/const-fn-type-name.rs rename src/test/run-pass/{ => consts}/const-int-conversion.rs (50%) rename src/test/run-pass/{ => consts}/const-int-overflowing.rs (54%) create mode 100644 src/test/run-pass/consts/const-int-rotate.rs rename src/test/run-pass/{ => consts}/const-int-saturating-arith.rs (100%) create mode 100644 src/test/run-pass/consts/const-int-sign.rs rename src/test/run-pass/{ => consts}/const-int-wrapping.rs (54%) rename src/test/run-pass/{ => consts}/const-needs_drop.rs (100%) rename src/test/run-pass/{ctfe => consts}/deref_in_pattern.rs (100%) rename src/test/run-pass/{ctfe => consts}/ice-48279.rs (100%) rename src/test/run-pass/{ctfe => consts}/issue-37550.rs (100%) rename src/test/run-pass/{ctfe => consts}/issue-broken-mir.rs (100%) rename src/test/run-pass/{ctfe => consts}/locals-in-const-fn.rs (100%) rename src/test/run-pass/{ctfe => consts}/match-const-fn-structs.rs (100%) rename src/test/run-pass/{ctfe => consts}/mozjs-error.rs (100%) rename src/test/run-pass/{ctfe => consts}/non-scalar-cast.rs (100%) rename src/test/run-pass/{ctfe => consts}/promotion.rs (100%) rename src/test/run-pass/{ctfe => consts}/references.rs (100%) rename src/test/run-pass/{ctfe => consts}/repeat_match.rs (100%) rename src/test/run-pass/{ctfe => consts}/return-in-const-fn.rs (100%) rename src/test/run-pass/{ctfe => consts}/signed_enum_discr.rs (100%) rename src/test/run-pass/{ctfe => consts}/transmute-const.rs (100%) rename src/test/run-pass/{ctfe => consts}/tuple-struct-constructors.rs (100%) create mode 100644 src/test/run-pass/generator/addassign-yield.rs create mode 100644 src/test/run-pass/generator/drop-and-replace.rs create mode 100644 src/test/run-pass/generator/overlap-locals.rs create mode 100644 src/test/run-pass/generator/size-moved-locals.rs create mode 100644 src/test/run-pass/issues/issue-61894.rs create mode 100644 src/test/run-pass/macros/macro-at-most-once-rep-2015.rs create mode 100644 src/test/run-pass/macros/macro-at-most-once-rep-2018.rs delete mode 100644 src/test/run-pass/macros/macro-at-most-once-rep.rs delete mode 100644 src/test/run-pass/methods/method-attributes.rs create mode 100644 src/test/run-pass/struct-ctor-mangling.rs delete mode 100644 src/test/run-pass/structs-enums/class-attributes-1.rs delete mode 100644 src/test/run-pass/structs-enums/class-attributes-2.rs delete mode 100644 src/test/run-pass/type-alias-enum-variants-2.rs delete mode 100644 src/test/run-pass/type-alias-enum-variants.rs delete mode 100644 src/test/run-pass/unsized-locals/fnbox-compat.rs create mode 100644 src/test/rustdoc-ui/failed-doctest-compile-fail.rs create mode 100644 src/test/rustdoc-ui/failed-doctest-compile-fail.stdout create mode 100644 src/test/rustdoc-ui/failed-doctest-missing-codes.rs create mode 100644 src/test/rustdoc-ui/failed-doctest-missing-codes.stdout create mode 100644 src/test/rustdoc-ui/failed-doctest-should-panic.rs create mode 100644 src/test/rustdoc-ui/failed-doctest-should-panic.stdout create mode 100644 src/test/rustdoc/const-generics/add-impl.rs create mode 100644 src/test/rustdoc/const-generics/const-generic-slice.rs rename src/test/rustdoc/{generic-const.rs => const-generics/const-impl.rs} (99%) create mode 100644 src/test/rustdoc/deep-structures.rs create mode 100644 src/test/rustdoc/issue-60726.rs create mode 100644 src/test/rustdoc/synthetic_auto/crate-local.rs create mode 100644 src/test/ui/annotate-snippet/missing-type.rs create mode 100644 src/test/ui/annotate-snippet/missing-type.stderr create mode 100644 src/test/ui/associated-type-bounds/auxiliary/fn-aux.rs create mode 100644 src/test/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs create mode 100644 src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs create mode 100644 src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr create mode 100644 src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs create mode 100644 src/test/ui/associated-type-bounds/duplicate.rs create mode 100644 src/test/ui/associated-type-bounds/duplicate.stderr create mode 100644 src/test/ui/associated-type-bounds/dyn-existential-type.rs create mode 100644 src/test/ui/associated-type-bounds/dyn-lcsit.rs create mode 100644 src/test/ui/associated-type-bounds/dyn-lcsit.stderr create mode 100644 src/test/ui/associated-type-bounds/dyn-rpit-and-let.rs create mode 100644 src/test/ui/associated-type-bounds/entails-sized-object-safety.rs create mode 100644 src/test/ui/associated-type-bounds/enum-bounds.rs create mode 100644 src/test/ui/associated-type-bounds/existential-type.rs create mode 100644 src/test/ui/associated-type-bounds/fn-apit.rs create mode 100644 src/test/ui/associated-type-bounds/fn-aux.rs create mode 100644 src/test/ui/associated-type-bounds/fn-dyn-apit.rs create mode 100644 src/test/ui/associated-type-bounds/fn-inline.rs create mode 100644 src/test/ui/associated-type-bounds/fn-where.rs create mode 100644 src/test/ui/associated-type-bounds/fn-wrap-apit.rs create mode 100644 src/test/ui/associated-type-bounds/implied-region-constraints.nll.stderr create mode 100644 src/test/ui/associated-type-bounds/implied-region-constraints.rs create mode 100644 src/test/ui/associated-type-bounds/implied-region-constraints.stderr create mode 100644 src/test/ui/associated-type-bounds/inside-adt.rs create mode 100644 src/test/ui/associated-type-bounds/inside-adt.stderr create mode 100644 src/test/ui/associated-type-bounds/lcsit.rs create mode 100644 src/test/ui/associated-type-bounds/lcsit.stderr create mode 100644 src/test/ui/associated-type-bounds/rpit.rs create mode 100644 src/test/ui/associated-type-bounds/struct-bounds.rs create mode 100644 src/test/ui/associated-type-bounds/trait-params.rs create mode 100644 src/test/ui/associated-type-bounds/type-alias.rs create mode 100644 src/test/ui/associated-type-bounds/type-alias.stderr create mode 100644 src/test/ui/associated-type-bounds/union-bounds.rs rename src/test/{run-pass => ui/async-await}/async-await.rs (92%) create mode 100644 src/test/ui/async-await/async-fn-nonsend.rs create mode 100644 src/test/ui/async-await/async-fn-nonsend.stderr rename src/test/ui/{ => async-await}/async-fn-path-elision.rs (100%) rename src/test/ui/{ => async-await}/async-fn-path-elision.stderr (100%) create mode 100644 src/test/ui/async-await/async-fn-send-uses-nonsend.rs rename src/test/ui/{ => async-await}/async-matches-expr.rs (100%) rename src/test/ui/{ => async-await}/async-with-closure.rs (86%) rename src/test/ui/{ => async-await}/await-keyword/2015-edition-error-in-non-macro-position.rs (100%) rename src/test/ui/{ => async-await}/await-keyword/2015-edition-error-in-non-macro-position.stderr (100%) rename src/test/ui/{ => async-await}/await-keyword/2015-edition-warning.fixed (100%) rename src/test/ui/{ => async-await}/await-keyword/2015-edition-warning.rs (100%) rename src/test/ui/{ => async-await}/await-keyword/2015-edition-warning.stderr (100%) rename src/test/ui/{ => async-await}/await-keyword/2018-edition-error-in-non-macro-position.rs (100%) rename src/test/ui/{ => async-await}/await-keyword/2018-edition-error-in-non-macro-position.stderr (100%) rename src/test/ui/{ => async-await}/await-keyword/2018-edition-error.rs (100%) rename src/test/ui/{ => async-await}/await-keyword/2018-edition-error.stderr (100%) rename src/test/ui/{ => async-await}/await-keyword/incorrect-syntax-suggestions.rs (100%) rename src/test/ui/{ => async-await}/await-keyword/incorrect-syntax-suggestions.stderr (100%) rename src/test/ui/{ => async-await}/await-keyword/post_expansion_error.rs (100%) rename src/test/ui/{ => async-await}/await-keyword/post_expansion_error.stderr (100%) rename src/test/{run-pass => ui/async-await}/await-macro.rs (98%) create mode 100644 src/test/ui/async-await/dont-print-desugared-async.rs create mode 100644 src/test/ui/async-await/dont-print-desugared-async.stderr create mode 100644 src/test/ui/async-await/dont-suggest-missing-await.rs create mode 100644 src/test/ui/async-await/dont-suggest-missing-await.stderr create mode 100644 src/test/ui/async-await/drop-order/auxiliary/arc_wake.rs rename src/test/ui/async-await/{ => drop-order}/drop-order-for-async-fn-parameters-by-ref-binding.rs (100%) rename src/test/ui/async-await/{ => drop-order}/drop-order-for-async-fn-parameters.rs (100%) rename src/test/ui/async-await/{ => drop-order}/drop-order-locals-are-hidden.rs (100%) rename src/test/ui/async-await/{ => drop-order}/drop-order-locals-are-hidden.stderr (100%) rename src/test/ui/{editions => async-await}/edition-deny-async-fns-2015.rs (86%) rename src/test/ui/{editions => async-await}/edition-deny-async-fns-2015.stderr (84%) create mode 100644 src/test/ui/async-await/generics-and-bounds.rs create mode 100644 src/test/ui/async-await/issue-61452.rs create mode 100644 src/test/ui/async-await/issue-61452.stderr create mode 100644 src/test/ui/async-await/issue-61793.rs rename src/test/ui/async-await/{ => issues}/auxiliary/issue-60674.rs (100%) rename src/test/ui/{ => async-await}/issues/issue-51719.rs (61%) rename src/test/ui/{ => async-await}/issues/issue-51719.stderr (63%) rename src/test/ui/{ => async-await}/issues/issue-51751.rs (100%) rename src/test/ui/{ => async-await}/issues/issue-51751.stderr (100%) rename src/test/ui/{ => async-await/issues}/issue-53249.rs (92%) rename src/test/{pretty => ui/async-await/issues}/issue-54752-async-block.rs (90%) rename src/test/ui/{ => async-await}/issues/issue-54974.rs (82%) rename src/test/ui/{ => async-await}/issues/issue-55324.rs (100%) rename src/test/{run-pass => ui/async-await/issues}/issue-55809.rs (100%) rename src/test/ui/{ => async-await}/issues/issue-58885.rs (100%) rename src/test/ui/{ => async-await}/issues/issue-59001.rs (100%) rename src/test/{run-pass/generator => ui/async-await/issues}/issue-59972.rs (96%) rename src/test/ui/async-await/{ => issues}/issue-60518.rs (100%) rename src/test/ui/{existential_types => async-await/issues}/issue-60655-latebound-regions.rs (100%) rename src/test/ui/async-await/{ => issues}/issue-60674.rs (100%) rename src/test/ui/async-await/{ => issues}/issue-60674.stdout (100%) create mode 100644 src/test/ui/async-await/issues/issue-61187.rs create mode 100644 src/test/ui/async-await/issues/issue-61187.stderr create mode 100644 src/test/ui/async-await/issues/issue-61986.rs create mode 100644 src/test/ui/async-await/issues/issue-62009.rs create mode 100644 src/test/ui/async-await/issues/issue-62009.stderr create mode 100644 src/test/ui/async-await/multiple-lifetimes/elided.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/hrtb.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/named.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/partial-relation.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-ref.rs create mode 100644 src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr create mode 100644 src/test/ui/async-await/multiple-lifetimes/variance.rs rename src/test/ui/{ => async-await}/no-args-non-move-async-closure.rs (100%) rename src/test/ui/{ => async-await}/no-args-non-move-async-closure.stderr (100%) create mode 100644 src/test/ui/async-await/no-async-const.rs create mode 100644 src/test/ui/async-await/no-async-const.stderr create mode 100644 src/test/ui/async-await/no-const-async.rs create mode 100644 src/test/ui/async-await/no-const-async.stderr create mode 100644 src/test/ui/async-await/no-unsafe-async.rs create mode 100644 src/test/ui/async-await/no-unsafe-async.stderr rename src/test/ui/{impl-trait => async-await}/recursive-async-impl-trait-type.rs (100%) rename src/test/ui/{impl-trait => async-await}/recursive-async-impl-trait-type.stderr (100%) create mode 100644 src/test/ui/async-await/suggest-missing-await.fixed create mode 100644 src/test/ui/async-await/suggest-missing-await.rs create mode 100644 src/test/ui/async-await/suggest-missing-await.stderr rename src/test/ui/{generator => async-await}/unresolved_type_param.rs (71%) rename src/test/ui/{generator => async-await}/unresolved_type_param.stderr (68%) delete mode 100644 src/test/ui/async-fn-multiple-lifetimes.rs delete mode 100644 src/test/ui/async-fn-multiple-lifetimes.stderr create mode 100644 src/test/ui/attributes/attr-before-view-item.rs create mode 100644 src/test/ui/attributes/attr-before-view-item2.rs create mode 100644 src/test/ui/attributes/attr-mix-new.rs rename src/test/ui/{attrs-with-no-formal-in-generics => attributes}/attrs-with-no-formal-in-generics-1.rs (100%) rename src/test/ui/{attrs-with-no-formal-in-generics => attributes}/attrs-with-no-formal-in-generics-1.stderr (100%) rename src/test/ui/{attrs-with-no-formal-in-generics => attributes}/attrs-with-no-formal-in-generics-2.rs (100%) rename src/test/ui/{attrs-with-no-formal-in-generics => attributes}/attrs-with-no-formal-in-generics-2.stderr (100%) rename src/test/ui/{attrs-with-no-formal-in-generics => attributes}/attrs-with-no-formal-in-generics-3.rs (100%) rename src/test/ui/{attrs-with-no-formal-in-generics => attributes}/attrs-with-no-formal-in-generics-3.stderr (100%) create mode 100644 src/test/ui/attributes/class-attributes-1.rs create mode 100644 src/test/ui/attributes/class-attributes-2.rs rename src/test/{run-pass => ui/attributes}/item-attributes.rs (54%) create mode 100644 src/test/ui/attributes/method-attributes.rs create mode 100644 src/test/ui/attributes/obsolete-attr.rs create mode 100644 src/test/ui/attributes/obsolete-attr.stderr create mode 100644 src/test/ui/attributes/unknown-attr.rs create mode 100644 src/test/ui/attributes/unknown-attr.stderr rename src/test/{run-pass => ui/attributes}/variant-attributes.rs (63%) create mode 100644 src/test/ui/borrowck/return-local-binding-from-desugaring.rs create mode 100644 src/test/ui/borrowck/return-local-binding-from-desugaring.stderr rename src/test/ui/{cast_char.rs => cast-char.rs} (100%) rename src/test/ui/{cast_char.stderr => cast-char.stderr} (85%) create mode 100644 src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs create mode 100644 src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr create mode 100644 src/test/ui/conditional-compilation/cfg-generic-params.rs create mode 100644 src/test/ui/conditional-compilation/cfg-generic-params.stderr create mode 100644 src/test/ui/const-generics/apit-with-const-param.rs create mode 100644 src/test/ui/const-generics/apit-with-const-param.stderr create mode 100644 src/test/ui/const-generics/array-wrapper-struct-ctor.rs create mode 100644 src/test/ui/const-generics/array-wrapper-struct-ctor.stderr create mode 100644 src/test/ui/const-generics/broken-mir-1.rs create mode 100644 src/test/ui/const-generics/broken-mir-1.stderr create mode 100644 src/test/ui/const-generics/broken-mir-2.rs create mode 100644 src/test/ui/const-generics/broken-mir-2.stderr create mode 100644 src/test/ui/const-generics/condition-in-trait-const-arg.rs create mode 100644 src/test/ui/const-generics/condition-in-trait-const-arg.stderr create mode 100644 src/test/ui/const-generics/const-generic-array-wrapper.rs create mode 100644 src/test/ui/const-generics/const-generic-array-wrapper.stderr create mode 100644 src/test/ui/const-generics/derive-debug-array-wrapper.rs create mode 100644 src/test/ui/const-generics/derive-debug-array-wrapper.stderr create mode 100644 src/test/ui/const-generics/fn-taking-const-generic-array.rs create mode 100644 src/test/ui/const-generics/fn-taking-const-generic-array.stderr create mode 100644 src/test/ui/const-generics/issue-60818-struct-constructors.rs create mode 100644 src/test/ui/const-generics/issue-60818-struct-constructors.stderr create mode 100644 src/test/ui/const-generics/issue-61336-1.rs create mode 100644 src/test/ui/const-generics/issue-61336-1.stderr create mode 100644 src/test/ui/const-generics/issue-61336-2.rs create mode 100644 src/test/ui/const-generics/issue-61336-2.stderr create mode 100644 src/test/ui/const-generics/issue-61336.rs create mode 100644 src/test/ui/const-generics/issue-61336.stderr create mode 100644 src/test/ui/const-generics/issue-61422.rs create mode 100644 src/test/ui/const-generics/issue-61422.stderr create mode 100644 src/test/ui/const-generics/mut-ref-const-param-array.rs create mode 100644 src/test/ui/const-generics/mut-ref-const-param-array.stderr create mode 100644 src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs create mode 100644 src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr create mode 100644 src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs create mode 100644 src/test/ui/const-generics/uninferred-consts-during-codegen-1.stderr create mode 100644 src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs create mode 100644 src/test/ui/const-generics/uninferred-consts-during-codegen-2.stderr create mode 100644 src/test/ui/consts/const_arg_promotable2.rs create mode 100644 src/test/ui/consts/const_arg_promotable2.stderr create mode 100644 src/test/ui/consts/const_constructor/const-construct-call.rs create mode 100644 src/test/ui/consts/const_constructor/feature-gate-const_constructor.const_fn.stderr create mode 100644 src/test/ui/consts/const_constructor/feature-gate-const_constructor.min_const_fn.stderr create mode 100644 src/test/ui/consts/const_constructor/feature-gate-const_constructor.rs create mode 100644 src/test/ui/consts/enum-discr-type-err.rs create mode 100644 src/test/ui/consts/enum-discr-type-err.stderr create mode 100644 src/test/ui/consts/issue-62045.rs create mode 100644 src/test/ui/consts/miri_unleashed/mutable_references.rs create mode 100644 src/test/ui/consts/miri_unleashed/mutable_references.stderr create mode 100644 src/test/ui/consts/miri_unleashed/mutable_references_ice.rs create mode 100644 src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr create mode 100644 src/test/ui/consts/packed_pattern.rs create mode 100644 src/test/ui/consts/packed_pattern2.rs create mode 100644 src/test/ui/consts/static-cycle-error.rs create mode 100644 src/test/ui/consts/static-raw-pointer-interning.rs create mode 100644 src/test/ui/consts/static-raw-pointer-interning2.rs rename src/test/ui/{ => consts}/underscore_const_names.rs (88%) create mode 100644 src/test/ui/consts/uninhabited-const-issue-61744.rs create mode 100644 src/test/ui/consts/uninhabited-const-issue-61744.stderr delete mode 100644 src/test/ui/custom-derive/auxiliary/plugin.rs delete mode 100644 src/test/ui/custom-derive/derive-in-mod.rs delete mode 100644 src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs delete mode 100644 src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr delete mode 100644 src/test/ui/custom-derive/helper-attr-blocked-by-import.rs delete mode 100644 src/test/ui/custom-derive/issue-36935.rs delete mode 100644 src/test/ui/custom-derive/issue-36935.stderr create mode 100644 src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs create mode 100644 src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr create mode 100644 src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs rename src/test/{run-pass => ui/enum-discriminant}/discriminant_value-wrapper.rs (97%) rename src/test/{run-pass => ui/enum-discriminant}/discriminant_value.rs (78%) create mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs create mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr rename src/test/ui/{ => error-codes}/E0501.rs (100%) rename src/test/ui/{ => error-codes}/E0501.stderr (100%) rename src/test/ui/{ => error-codes}/E0506.rs (100%) rename src/test/ui/{ => error-codes}/E0506.stderr (100%) rename src/test/ui/{ => error-codes}/E0508-fail.rs (100%) rename src/test/ui/{ => error-codes}/E0508-fail.stderr (78%) rename src/test/ui/{ => error-codes}/E0508.rs (100%) rename src/test/ui/{ => error-codes}/E0508.stderr (77%) rename src/test/ui/{ => error-codes}/E0583.rs (100%) rename src/test/ui/{ => error-codes}/E0583.stderr (100%) rename src/test/ui/{ => error-codes}/E0594.rs (100%) rename src/test/ui/{ => error-codes}/E0594.stderr (100%) rename src/test/ui/{ => error-codes}/E0596.rs (100%) rename src/test/ui/{ => error-codes}/E0596.stderr (100%) rename src/test/ui/{ => error-codes}/E0642.rs (100%) rename src/test/ui/{ => error-codes}/E0642.stderr (100%) rename src/test/ui/{ => error-codes}/E0660.rs (100%) rename src/test/ui/{ => error-codes}/E0660.stderr (100%) rename src/test/ui/{ => error-codes}/E0661.rs (100%) rename src/test/ui/{ => error-codes}/E0661.stderr (100%) rename src/test/ui/{ => error-codes}/E0662.rs (100%) rename src/test/ui/{ => error-codes}/E0662.stderr (100%) rename src/test/ui/{ => error-codes}/E0663.rs (100%) rename src/test/ui/{ => error-codes}/E0663.stderr (100%) rename src/test/ui/{ => error-codes}/E0664.rs (100%) rename src/test/ui/{ => error-codes}/E0664.stderr (100%) rename src/test/ui/{ => error-codes}/E0665.rs (100%) rename src/test/ui/{ => error-codes}/E0665.stderr (100%) rename src/test/ui/{ => error-codes}/E0705.rs (100%) rename src/test/ui/{ => error-codes}/E0705.stderr (100%) create mode 100644 src/test/ui/error-codes/E0730.rs create mode 100644 src/test/ui/error-codes/E0730.stderr rename src/test/ui/{ => error-codes}/e0119/auxiliary/complex_impl_support.rs (100%) rename src/test/ui/{ => error-codes}/e0119/auxiliary/issue-23563-a.rs (100%) rename src/test/ui/{ => error-codes}/e0119/complex-impl.rs (100%) rename src/test/ui/{ => error-codes}/e0119/complex-impl.stderr (100%) rename src/test/ui/{ => error-codes}/e0119/conflict-with-std.rs (100%) rename src/test/ui/{ => error-codes}/e0119/conflict-with-std.stderr (100%) rename src/test/ui/{ => error-codes}/e0119/issue-23563.rs (100%) rename src/test/ui/{ => error-codes}/e0119/issue-23563.stderr (100%) rename src/test/ui/{ => error-codes}/e0119/issue-27403.rs (100%) rename src/test/ui/{ => error-codes}/e0119/issue-27403.stderr (100%) rename src/test/ui/{ => error-codes}/e0119/issue-28981.rs (100%) rename src/test/ui/{ => error-codes}/e0119/issue-28981.stderr (100%) rename src/test/ui/{ => error-codes}/e0119/so-37347311.rs (100%) rename src/test/ui/{ => error-codes}/e0119/so-37347311.stderr (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs create mode 100644 src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-member-constraints.rs create mode 100644 src/test/ui/feature-gates/feature-gate-member-constraints.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-repr_align_enum.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-transparent_enums.rs create mode 100644 src/test/ui/feature-gates/feature-gate-transparent_enums.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-transparent_unions.rs create mode 100644 src/test/ui/feature-gates/feature-gate-transparent_unions.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-underscore_const_names.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr delete mode 100644 src/test/ui/feature-gates/underscore_const_names_feature_gate.rs delete mode 100644 src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr create mode 100644 src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs create mode 100644 src/test/ui/impl-trait/hidden-lifetimes.rs create mode 100644 src/test/ui/impl-trait/hidden-lifetimes.stderr rename src/test/ui/impl-trait/{ => issues}/infinite-impl-trait-issue-38064.rs (100%) rename src/test/ui/impl-trait/{ => issues}/infinite-impl-trait-issue-38064.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-21659-show-relevant-trait-impls-3.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-21659-show-relevant-trait-impls-3.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-42479.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-49376.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-52128.rs (100%) create mode 100644 src/test/ui/impl-trait/issues/issue-53457.rs rename src/test/ui/impl-trait/{ => issues}/issue-55608-captures-empty-region.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57464-unexpected-regions.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-impl-trait-in-path.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-impl-trait-in-path.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-nested-impl-trait-in-assoc-proj.rs (100%) rename src/test/ui/impl-trait/{ => issues}/issue-57979-nested-impl-trait-in-assoc-proj.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/universal-issue-48703.rs (100%) rename src/test/ui/impl-trait/{ => issues}/universal-issue-48703.stderr (100%) rename src/test/ui/impl-trait/{ => issues}/universal-turbofish-in-method-issue-50950.rs (100%) rename src/test/ui/impl-trait/{ => issues}/universal-turbofish-in-method-issue-50950.stderr (100%) create mode 100644 src/test/ui/impl-trait/multiple-lifetimes.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-existential.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr delete mode 100644 src/test/ui/impl-trait/needs_least_region_or_bound.stderr create mode 100644 src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.rs create mode 100644 src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr create mode 100644 src/test/ui/intrinsics/unchecked_math_unsafe.rs create mode 100644 src/test/ui/intrinsics/unchecked_math_unsafe.stderr create mode 100644 src/test/ui/intrinsics/unchecked_math_unstable.rs create mode 100644 src/test/ui/intrinsics/unchecked_math_unstable.stderr create mode 100644 src/test/ui/issue-53912.rs rename src/test/ui/{ => issues}/auxiliary/issue-59764.rs (100%) create mode 100644 src/test/ui/issues/issue-21596.rs create mode 100644 src/test/ui/issues/issue-21596.stderr create mode 100644 src/test/ui/issues/issue-27697.rs create mode 100644 src/test/ui/issues/issue-38591.rs delete mode 100644 src/test/ui/issues/issue-51279.rs delete mode 100644 src/test/ui/issues/issue-51279.stderr create mode 100644 src/test/ui/issues/issue-51301.rs create mode 100644 src/test/ui/issues/issue-51301.stderr create mode 100644 src/test/ui/issues/issue-54189.rs create mode 100644 src/test/ui/issues/issue-54189.stderr rename src/test/ui/{ => issues}/issue-59508-1.rs (100%) rename src/test/ui/{ => issues}/issue-59508-1.stderr (100%) rename src/test/ui/{ => issues}/issue-59508.fixed (100%) rename src/test/ui/{ => issues}/issue-59508.rs (100%) rename src/test/ui/{ => issues}/issue-59508.stderr (100%) rename src/test/ui/{ => issues}/issue-59756.fixed (100%) rename src/test/ui/{ => issues}/issue-59756.rs (100%) rename src/test/ui/{ => issues}/issue-59756.stderr (100%) rename src/test/ui/{ => issues}/issue-59764.rs (100%) rename src/test/ui/{ => issues}/issue-59764.stderr (100%) rename src/test/ui/{ => issues}/issue-60075.rs (100%) rename src/test/ui/{ => issues}/issue-60075.stderr (100%) rename src/test/ui/{ => issues}/issue-60622.rs (100%) rename src/test/ui/{ => issues}/issue-60622.stderr (100%) create mode 100644 src/test/ui/issues/issue-61106.rs create mode 100644 src/test/ui/issues/issue-61106.stderr create mode 100644 src/test/ui/issues/issue-61108.rs create mode 100644 src/test/ui/issues/issue-61108.stderr create mode 100644 src/test/ui/issues/issue-61858.rs create mode 100644 src/test/ui/issues/issue-61858.stderr create mode 100644 src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs create mode 100644 src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs create mode 100644 src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs create mode 100644 src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr create mode 100644 src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs create mode 100644 src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr create mode 100644 src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs create mode 100644 src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr rename src/test/ui/{ => linkage-attr}/linkage2.rs (81%) rename src/test/ui/{ => linkage-attr}/linkage2.stderr (70%) rename src/test/ui/{ => linkage-attr}/linkage3.rs (100%) rename src/test/ui/{ => linkage-attr}/linkage3.stderr (100%) rename src/test/ui/{ => linkage-attr}/linkage4.rs (100%) rename src/test/ui/{ => linkage-attr}/linkage4.stderr (100%) create mode 100644 src/test/ui/lint/lint-match-arms.rs create mode 100644 src/test/ui/lint/lint-match-arms.stderr delete mode 100644 src/test/ui/lint/lint-obsolete-attr.rs delete mode 100644 src/test/ui/lint/lint-obsolete-attr.stderr delete mode 100644 src/test/ui/lint/lint-unknown-attr.rs delete mode 100644 src/test/ui/lint/lint-unknown-attr.stderr create mode 100644 src/test/ui/lint/must_use-array.rs create mode 100644 src/test/ui/lint/must_use-array.stderr create mode 100644 src/test/ui/lint/must_use-tuple.rs create mode 100644 src/test/ui/lint/must_use-tuple.stderr delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.stderr create mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015.rs create mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015.stderr create mode 100644 src/test/ui/nll/assign-while-to-immutable.rs create mode 100644 src/test/ui/nll/dont-print-desugared.rs create mode 100644 src/test/ui/nll/dont-print-desugared.stderr create mode 100644 src/test/ui/nll/empty-type-predicate.rs create mode 100644 src/test/ui/nll/issue-61311-normalize.rs create mode 100644 src/test/ui/nll/issue-61320-normalize.rs create mode 100644 src/test/ui/nll/issue-61424.rs create mode 100644 src/test/ui/nll/issue-61424.stderr create mode 100644 src/test/ui/nll/issue-62007-assign-const-index.rs create mode 100644 src/test/ui/nll/issue-62007-assign-const-index.stderr create mode 100644 src/test/ui/nll/issue-62007-assign-differing-fields.rs create mode 100644 src/test/ui/nll/issue-62007-assign-differing-fields.stderr create mode 100644 src/test/ui/nll/user-annotations/adt-tuple-struct-calls.rs create mode 100644 src/test/ui/nll/user-annotations/adt-tuple-struct-calls.stderr create mode 100644 src/test/ui/obsolete-in-place/bad.stderr create mode 100644 src/test/ui/parser/issue-62546.rs create mode 100644 src/test/ui/parser/issue-62546.stderr create mode 100644 src/test/ui/parser/issue-62660.rs create mode 100644 src/test/ui/parser/issue-62660.stderr create mode 100644 src/test/ui/parser/issue-62881.rs create mode 100644 src/test/ui/parser/issue-62881.stderr create mode 100644 src/test/ui/parser/issue-62895.rs create mode 100644 src/test/ui/parser/issue-62895.stderr create mode 100644 src/test/ui/parser/macro/bad-macro-argument.rs create mode 100644 src/test/ui/parser/macro/bad-macro-argument.stderr create mode 100644 src/test/ui/parser/self-in-function-arg.rs create mode 100644 src/test/ui/parser/self-in-function-arg.stderr create mode 100644 src/test/ui/parser/underscore_item_not_const.rs create mode 100644 src/test/ui/parser/underscore_item_not_const.stderr delete mode 100644 src/test/ui/parser/underscore_static.rs delete mode 100644 src/test/ui/parser/underscore_static.stderr delete mode 100644 src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/attribute-with-error.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-a-b.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-a.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-panic.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/dollar-crate.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/issue-41211.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/issue-53481.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/macro-brackets.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/nested-item-spans.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/span-preservation.rs create mode 100644 src/test/ui/proc-macro/derive-in-mod.rs create mode 100644 src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs create mode 100644 src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr create mode 100644 src/test/ui/proc-macro/helper-attr-blocked-by-import.rs create mode 100644 src/test/ui/proc-macro/issue-36935.rs create mode 100644 src/test/ui/proc-macro/issue-36935.stderr create mode 100644 src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout create mode 100644 src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr create mode 100644 src/test/ui/rfc-2497-if-let-chains/feature-gate.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr create mode 100644 src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs delete mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs delete mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr delete mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs delete mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr create mode 100644 src/test/ui/save-analysis/emit-notifications.nll.stderr create mode 100644 src/test/ui/save-analysis/emit-notifications.rs create mode 100644 src/test/ui/save-analysis/emit-notifications.stderr create mode 100644 src/test/ui/self/elision/README.md create mode 100644 src/test/ui/self/elision/alias.rs create mode 100644 src/test/ui/self/elision/assoc.rs create mode 100644 src/test/ui/self/elision/lt-alias.rs create mode 100644 src/test/ui/self/elision/lt-assoc.rs create mode 100644 src/test/ui/self/elision/lt-ref-self.nll.stderr create mode 100644 src/test/ui/self/elision/lt-ref-self.rs create mode 100644 src/test/ui/self/elision/lt-ref-self.stderr create mode 100644 src/test/ui/self/elision/lt-self.rs create mode 100644 src/test/ui/self/elision/lt-struct.rs create mode 100644 src/test/ui/self/elision/multiple-ref-self.rs create mode 100644 src/test/ui/self/elision/ref-alias.rs create mode 100644 src/test/ui/self/elision/ref-assoc.rs create mode 100644 src/test/ui/self/elision/ref-mut-alias.rs create mode 100644 src/test/ui/self/elision/ref-mut-self.nll.stderr create mode 100644 src/test/ui/self/elision/ref-mut-self.rs create mode 100644 src/test/ui/self/elision/ref-mut-self.stderr create mode 100644 src/test/ui/self/elision/ref-mut-struct.nll.stderr create mode 100644 src/test/ui/self/elision/ref-mut-struct.rs create mode 100644 src/test/ui/self/elision/ref-mut-struct.stderr create mode 100644 src/test/ui/self/elision/ref-self.nll.stderr create mode 100644 src/test/ui/self/elision/ref-self.rs create mode 100644 src/test/ui/self/elision/ref-self.stderr create mode 100644 src/test/ui/self/elision/ref-struct.nll.stderr create mode 100644 src/test/ui/self/elision/ref-struct.rs create mode 100644 src/test/ui/self/elision/ref-struct.stderr create mode 100644 src/test/ui/self/elision/self.rs create mode 100644 src/test/ui/self/elision/struct.rs create mode 100644 src/test/ui/suggestions/issue-52820.rs create mode 100644 src/test/ui/suggestions/issue-52820.stderr create mode 100644 src/test/ui/suggestions/mut-ref-reassignment.rs create mode 100644 src/test/ui/suggestions/mut-ref-reassignment.stderr create mode 100644 src/test/ui/suggestions/option-content-move.fixed create mode 100644 src/test/ui/suggestions/option-content-move.rs create mode 100644 src/test/ui/suggestions/option-content-move.stderr create mode 100644 src/test/ui/symbol-names/basic.legacy.stderr create mode 100644 src/test/ui/symbol-names/basic.v0.stderr create mode 100644 src/test/ui/symbol-names/impl1.legacy.stderr create mode 100644 src/test/ui/symbol-names/impl1.v0.stderr create mode 100644 src/test/ui/symbol-names/impl2.rs create mode 100644 src/test/ui/symbol-names/impl2.stderr create mode 100644 src/test/ui/symbol-names/issue-60925.legacy.stderr create mode 100644 src/test/ui/symbol-names/issue-60925.rs create mode 100644 src/test/ui/symbol-names/issue-60925.stderr create mode 100644 src/test/ui/symbol-names/issue-60925.v0.stderr delete mode 100644 src/test/ui/traits/trait-alias-object.rs rename src/test/ui/traits/{ => trait-alias}/auxiliary/trait_alias.rs (100%) rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-bounds.rs (96%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-cross-crate.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-cross-crate.stderr (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-impl.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-impl.stderr (100%) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-object-fail.rs rename src/test/ui/traits/{trait-alias-object.stderr => trait-alias/trait-alias-object-fail.stderr} (70%) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-object-wf.rs rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-object.rs (96%) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr rename src/test/ui/traits/{trait-alias-syntax.rs => trait-alias/trait-alias-syntax-fail.rs} (100%) rename src/test/ui/traits/{trait-alias-syntax.stderr => trait-alias/trait-alias-syntax-fail.stderr} (77%) rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-syntax.rs (97%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-wf.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-wf.stderr (100%) rename src/test/ui/{run-pass/traits => traits/trait-alias}/trait-alias.rs (98%) create mode 100644 src/test/ui/traits/trait-with-dst.rs rename src/test/ui/{run-pass => }/traits/traits-static-outlives-a-where-clause.rs (100%) create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.rs create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.stderr create mode 100644 src/test/ui/traits/wf-trait-object-no-duplicates.rs create mode 100644 src/test/ui/traits/wf-trait-object-no-duplicates.stderr create mode 100644 src/test/ui/traits/wf-trait-object-only-maybe-bound.rs create mode 100644 src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr create mode 100644 src/test/ui/traits/wf-trait-object-reverse-order.rs delete mode 100644 src/test/ui/type-alias-enum-variants-panic.rs delete mode 100644 src/test/ui/type-alias-enum-variants-panic.stderr delete mode 100644 src/test/ui/type-alias-enum-variants-priority-2.rs delete mode 100644 src/test/ui/type-alias-enum-variants-priority-2.stderr delete mode 100644 src/test/ui/type-alias-enum-variants-priority-3.rs delete mode 100644 src/test/ui/type-alias-enum-variants-priority.rs delete mode 100644 src/test/ui/type-alias-enum-variants.rs rename src/test/ui/{pattern/enum-variant-generic-args.rs => type-alias-enum-variants/enum-variant-generic-args-pass.rs} (59%) rename src/test/ui/{ => type-alias-enum-variants}/enum-variant-generic-args.rs (65%) rename src/test/ui/{ => type-alias-enum-variants}/enum-variant-generic-args.stderr (58%) create mode 100644 src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs create mode 100644 src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr create mode 100644 src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs rename src/test/ui/{type-alias-enum-variants-priority.stderr => type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr} (74%) rename src/test/ui/{issues/issue-58006.rs => type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs} (86%) rename src/test/ui/{issues/issue-58006.stderr => type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr} (73%) create mode 100644 src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs create mode 100644 src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr rename src/test/ui/{issues => type-alias-enum-variants}/issue-57866.rs (88%) create mode 100644 src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs create mode 100644 src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs rename src/test/ui/{type-alias-enum-variants.stderr => type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr} (69%) create mode 100644 src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs rename src/test/ui/{type-alias-enum-variants-priority-3.stderr => type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr} (66%) create mode 100644 src/test/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs create mode 100644 src/test/ui/type-alias/issue-62263-self-in-atb.rs create mode 100644 src/test/ui/type-alias/issue-62263-self-in-atb.stderr create mode 100644 src/test/ui/type-alias/issue-62305-self-assoc-ty.rs create mode 100644 src/test/ui/type-alias/issue-62305-self-assoc-ty.stderr create mode 100644 src/test/ui/type-alias/issue-62364-self-ty-arg.rs create mode 100644 src/test/ui/type-alias/issue-62364-self-ty-arg.stderr create mode 100644 vendor/annotate-snippets/.cargo-checksum.json create mode 100644 vendor/annotate-snippets/Cargo.toml rename vendor/{unreachable => annotate-snippets}/LICENSE-APACHE (99%) create mode 100644 vendor/annotate-snippets/LICENSE-MIT create mode 100644 vendor/annotate-snippets/README.md create mode 100644 vendor/annotate-snippets/examples/expected_type.rs create mode 100644 vendor/annotate-snippets/examples/footer.rs create mode 100644 vendor/annotate-snippets/examples/format.rs create mode 100644 vendor/annotate-snippets/examples/multislice.rs create mode 100644 vendor/annotate-snippets/src/display_list/from_snippet.rs create mode 100644 vendor/annotate-snippets/src/display_list/mod.rs create mode 100644 vendor/annotate-snippets/src/display_list/structs.rs create mode 100644 vendor/annotate-snippets/src/formatter/mod.rs create mode 100644 vendor/annotate-snippets/src/formatter/style.rs create mode 100644 vendor/annotate-snippets/src/lib.rs create mode 100644 vendor/annotate-snippets/src/snippet.rs create mode 100644 vendor/annotate-snippets/src/stylesheets/color.rs create mode 100644 vendor/annotate-snippets/src/stylesheets/mod.rs create mode 100644 vendor/annotate-snippets/src/stylesheets/no_color.rs create mode 100644 vendor/annotate-snippets/tests/diff/mod.rs create mode 100644 vendor/annotate-snippets/tests/dl_from_snippet.rs create mode 100644 vendor/annotate-snippets/tests/fixtures.rs create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation.yaml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiline_annotation2.yaml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/multiple_annotations.yaml create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/simple.txt create mode 100644 vendor/annotate-snippets/tests/fixtures/no-color/simple.yaml create mode 100644 vendor/annotate-snippets/tests/formatter.rs create mode 100644 vendor/annotate-snippets/tests/snippet/mod.rs create mode 100644 vendor/autocfg/.cargo-checksum.json create mode 100644 vendor/autocfg/Cargo.toml rename vendor/{bitflags-0.9.1 => autocfg}/LICENSE-APACHE (100%) create mode 100644 vendor/autocfg/LICENSE-MIT create mode 100644 vendor/autocfg/README.md create mode 100644 vendor/autocfg/examples/integers.rs create mode 100644 vendor/autocfg/examples/paths.rs create mode 100644 vendor/autocfg/examples/traits.rs create mode 100644 vendor/autocfg/examples/versions.rs create mode 100644 vendor/autocfg/src/error.rs create mode 100644 vendor/autocfg/src/lib.rs create mode 100644 vendor/autocfg/src/tests.rs create mode 100644 vendor/autocfg/src/version.rs delete mode 100644 vendor/backtrace/appveyor.yml create mode 100644 vendor/backtrace/azure-pipelines.yml create mode 100644 vendor/backtrace/benches/benchmarks.rs create mode 100644 vendor/backtrace/build.rs create mode 100644 vendor/backtrace/ci/azure-install-rust.yml create mode 100644 vendor/backtrace/ci/azure-test-all.yml delete mode 100644 vendor/backtrace/ci/docker/powerpc-unknown-linux-gnu/Dockerfile create mode 100644 vendor/backtrace/src/dbghelp.rs delete mode 100644 vendor/backtrace/src/dylib.rs create mode 100644 vendor/backtrace/src/symbolize/dladdr_resolve.rs create mode 100644 vendor/backtrace/src/windows.rs create mode 100644 vendor/backtrace/tests/accuracy/auxiliary.rs create mode 100644 vendor/backtrace/tests/accuracy/main.rs delete mode 100644 vendor/bitflags-0.9.1/.cargo-checksum.json delete mode 100644 vendor/bitflags-0.9.1/README.md delete mode 100644 vendor/bitflags-0.9.1/src/example_generated.rs delete mode 100644 vendor/bitflags-0.9.1/src/lib.rs delete mode 100644 vendor/bitflags-0.9.1/tests/conflicting_trait_impls.rs delete mode 100644 vendor/bitflags-0.9.1/tests/external.rs delete mode 100644 vendor/bitflags-0.9.1/tests/external_no_std.rs delete mode 100644 vendor/bitflags-0.9.1/tests/i128_bitflags.rs delete mode 100644 vendor/compiler_builtins/compiler-rt/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/CODE_OWNERS.TXT delete mode 100644 vendor/compiler_builtins/compiler-rt/CREDITS.TXT delete mode 100644 vendor/compiler_builtins/compiler-rt/LICENSE.TXT delete mode 100644 vendor/compiler_builtins/compiler-rt/README.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/BlocksRuntime/Block.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/BlocksRuntime/Block_private.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/BlocksRuntime/data.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/BlocksRuntime/runtime.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/README.TXT delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios6-armv7s.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/ios7-arm64.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim-i386.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim-x86_64.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/iossim.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/osx-i386.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/osx.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/README.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/aarch64/chkstk.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/absvdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/absvsi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/absvti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/adddf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/addsf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/addtf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/addvdi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/addvsi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/addvti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/apple_versioning.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/adddf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/addsf3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/addsf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_dcmp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_div0.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_drsub.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_fcmp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_frsub.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_idivmod.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memcmp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memcpy.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memmove.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_memset.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/bswapdi2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/bswapsi2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/chkstk.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/clzdi2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/clzsi2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/comparesf2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/divdf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/divmodsi4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/divsf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/divsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/eqdf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/eqsf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/fixdfsivfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/fixsfsivfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/fixunssfsivfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/floatsidfvfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/floatsisfvfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/floatunssidfvfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/floatunssisfvfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/gedf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/gesf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/gtdf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/gtsf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/ledf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/lesf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/ltdf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/ltsf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/modsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/muldf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/mulsf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/nedf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/negdf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/negsf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/nesf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/softfloat-alias.list delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/subdf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/subsf3vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/switch16.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/switch32.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/switch8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/switchu8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync-ops.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/sync_synchronize.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/udivmodsi4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/udivsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/umodsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/unorddf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/arm/unordsf2vfp.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ashldi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ashlti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ashrdi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ashrti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/assembly.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/atomic.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/atomic_flag_clear.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/atomic_flag_clear_explicit.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/atomic_flag_test_and_set.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/atomic_flag_test_and_set_explicit.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/atomic_signal_fence.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/atomic_thread_fence.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/bswapdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/bswapsi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/clear_cache.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/clzdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/clzsi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/clzti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/cmpdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/cmpti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/comparedf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/comparesf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/comparetf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/cpu_model.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ctzdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ctzsi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ctzti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divdc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divdf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divdi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divmoddi4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divmodsi4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divsc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divsf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divsi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divtc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divtf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/divxc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/emutls.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/enable_execute_stack.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/eprintf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/extenddftf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/extendhfsf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/extendsfdf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/extendsftf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ffsdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ffssi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ffsti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixdfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixdfsi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixdfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixsfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixsfsi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixsfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixtfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixtfsi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixtfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunsdfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunsdfsi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunsdfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunssfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunssfsi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunssfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunstfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunstfsi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunstfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunsxfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunsxfsi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixunsxfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixxfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fixxfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatdidf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatdisf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatditf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatdixf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatsidf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatsisf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatsitf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floattidf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floattisf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floattitf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floattixf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatundidf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatundisf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatunditf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatundixf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatunsidf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatunsisf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatunsitf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatuntidf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatuntisf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatuntitf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/floatuntixf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_add_impl.inc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_extend.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_extend_impl.inc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_fixint_impl.inc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_fixuint_impl.inc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_lib.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_mul_impl.inc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_trunc.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/fp_trunc_impl.inc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/gcc_personality_v0.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/common_entry_exit_abi1.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/common_entry_exit_abi2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/common_entry_exit_legacy.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/dfaddsub.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/dfdiv.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/dffma.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/dfminmax.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/dfmul.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/dfsqrt.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/divdi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/divsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/fabs_opt.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/fastmath2_dlib_asm.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/fastmath2_ldlib_asm.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/fastmath_dlib_asm.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/fma_opt.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/fmax_opt.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/fmin_opt.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/memcpy_forward_vp4cp4n2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/memcpy_likely_aligned.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/moddi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/modsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/sfdiv_opt.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/sfsqrt_opt.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/udivdi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/udivmoddi4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/udivmodsi4.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/udivsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/umoddi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/hexagon/umodsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/ashldi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/ashrdi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/chkstk.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/chkstk2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/divdi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/floatdidf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/floatdisf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/floatdixf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/floatundidf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/floatundisf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/floatundixf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/lshrdi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/moddi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/muldi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/udivdi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/i386/umoddi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/int_endianness.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/int_lib.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/int_math.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/int_types.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/int_util.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/int_util.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/lshrdi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/lshrti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/macho_embedded/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/macho_embedded/arm.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/macho_embedded/common.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/macho_embedded/i386.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/macho_embedded/thumb2-64.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/macho_embedded/thumb2.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mingw_fixfloat.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/moddi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/modsi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/modti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/muldc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/muldf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/muldi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulodi4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulosi4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/muloti4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulsc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulsf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/multc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/multf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/multi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulvdi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulvsi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulvti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/mulxc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/negdf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/negdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/negsf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/negti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/negvdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/negvsi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/negvti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/os_version_check.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/paritydi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/paritysi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/parityti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/popcountdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/popcountsi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/popcountti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/powidf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/powisf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/powitf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/powixf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/DD.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/divtc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/fixtfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/fixunstfdi.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/fixunstfti.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/floatditf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/floattitf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/floatunditf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qadd.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qdiv.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qmul.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/gcc_qsub.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/multc3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/restFP.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ppc/saveFP.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/riscv/mulsi3.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/subdf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/subsf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/subtf3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/subvdi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/subvsi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/subvti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/trampoline_setup.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/truncdfhf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/truncdfsf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/truncsfhf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/trunctfdf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/trunctfsf2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ucmpdi2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/ucmpti2.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/udivdi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/udivmoddi4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/udivmodsi4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/udivmodti4.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/udivsi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/udivti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/umoddi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/umodsi3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/umodti3.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/unwind-ehabi-helpers.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/chkstk.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/chkstk2.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/floatdidf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/floatdisf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/floatdixf.c delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/floatundidf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/floatundisf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/builtins/x86_64/floatundixf.S delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/cfi/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/cfi/cfi.cc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/cfi/cfi_blacklist.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/safestack/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/safestack/safestack.cc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/stats/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/stats/stats.cc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/stats/stats.h delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/stats/stats_client.cc delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/ubsan_minimal/CMakeLists.txt delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/ubsan_minimal/ubsan.syms.extra delete mode 100644 vendor/compiler_builtins/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cc delete mode 100755 vendor/compiler_builtins/compiler-rt/utils/generate_netbsd_ioctls.awk delete mode 100755 vendor/compiler_builtins/compiler-rt/utils/generate_netbsd_syscalls.awk create mode 100644 vendor/compiler_builtins/libm/src/math/acosh.rs create mode 100644 vendor/compiler_builtins/libm/src/math/acoshf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/asinh.rs create mode 100644 vendor/compiler_builtins/libm/src/math/asinhf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/atanh.rs create mode 100644 vendor/compiler_builtins/libm/src/math/atanhf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/copysign.rs create mode 100644 vendor/compiler_builtins/libm/src/math/copysignf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/erf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/erff.rs create mode 100644 vendor/compiler_builtins/libm/src/math/exp10.rs create mode 100644 vendor/compiler_builtins/libm/src/math/exp10f.rs create mode 100644 vendor/compiler_builtins/libm/src/math/fmax.rs create mode 100644 vendor/compiler_builtins/libm/src/math/fmaxf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/fmin.rs create mode 100644 vendor/compiler_builtins/libm/src/math/fminf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/frexp.rs create mode 100644 vendor/compiler_builtins/libm/src/math/frexpf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/ilogb.rs create mode 100644 vendor/compiler_builtins/libm/src/math/ilogbf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/j0.rs create mode 100644 vendor/compiler_builtins/libm/src/math/j0f.rs create mode 100644 vendor/compiler_builtins/libm/src/math/j1.rs create mode 100644 vendor/compiler_builtins/libm/src/math/j1f.rs create mode 100644 vendor/compiler_builtins/libm/src/math/jn.rs create mode 100644 vendor/compiler_builtins/libm/src/math/jnf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/lgamma.rs create mode 100644 vendor/compiler_builtins/libm/src/math/lgamma_r.rs create mode 100644 vendor/compiler_builtins/libm/src/math/lgammaf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/lgammaf_r.rs create mode 100644 vendor/compiler_builtins/libm/src/math/modf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/modff.rs create mode 100644 vendor/compiler_builtins/libm/src/math/remquo.rs create mode 100644 vendor/compiler_builtins/libm/src/math/remquof.rs create mode 100644 vendor/compiler_builtins/libm/src/math/sincos.rs create mode 100644 vendor/compiler_builtins/libm/src/math/sincosf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/tgamma.rs create mode 100644 vendor/compiler_builtins/libm/src/math/tgammaf.rs create mode 100644 vendor/darling/.cargo-checksum.json create mode 100644 vendor/darling/CHANGELOG.md create mode 100644 vendor/darling/Cargo.toml rename vendor/{unreachable/LICENSE-MIT => darling/LICENSE} (95%) create mode 100644 vendor/darling/README.md create mode 100644 vendor/darling/examples/automatic_bounds.rs create mode 100644 vendor/darling/examples/consume_fields.rs create mode 100644 vendor/darling/examples/fallible_read.rs create mode 100644 vendor/darling/examples/supports_struct.rs create mode 100644 vendor/darling/src/lib.rs create mode 100644 vendor/darling/src/macros_public.rs create mode 100644 vendor/darling/tests/accrue_errors.rs create mode 100644 vendor/darling/tests/computed_bound.rs create mode 100644 vendor/darling/tests/custom_bound.rs create mode 100644 vendor/darling/tests/defaults.rs create mode 100644 vendor/darling/tests/enums_newtype.rs create mode 100644 vendor/darling/tests/enums_struct.rs create mode 100644 vendor/darling/tests/enums_unit.rs create mode 100644 vendor/darling/tests/error.rs create mode 100644 vendor/darling/tests/from_generics.rs create mode 100644 vendor/darling/tests/from_type_param.rs create mode 100644 vendor/darling/tests/from_type_param_default.rs create mode 100644 vendor/darling/tests/from_variant.rs create mode 100644 vendor/darling/tests/generics.rs create mode 100644 vendor/darling/tests/happy_path.rs create mode 100644 vendor/darling/tests/multiple.rs create mode 100644 vendor/darling/tests/newtype.rs create mode 100644 vendor/darling/tests/skip.rs create mode 100644 vendor/darling/tests/split_declaration.rs create mode 100644 vendor/darling/tests/suggestions.rs create mode 100644 vendor/darling/tests/supports.rs create mode 100644 vendor/darling_core/.cargo-checksum.json create mode 100644 vendor/darling_core/Cargo.toml rename vendor/{pulldown-cmark-0.1.2 => darling_core}/LICENSE (86%) create mode 100644 vendor/darling_core/src/ast/data.rs create mode 100644 vendor/darling_core/src/ast/generics.rs create mode 100644 vendor/darling_core/src/ast/mod.rs create mode 100644 vendor/darling_core/src/codegen/attr_extractor.rs create mode 100644 vendor/darling_core/src/codegen/default_expr.rs create mode 100644 vendor/darling_core/src/codegen/error.rs create mode 100644 vendor/darling_core/src/codegen/field.rs create mode 100644 vendor/darling_core/src/codegen/from_derive_impl.rs create mode 100644 vendor/darling_core/src/codegen/from_field.rs create mode 100644 vendor/darling_core/src/codegen/from_meta_impl.rs create mode 100644 vendor/darling_core/src/codegen/from_type_param.rs create mode 100644 vendor/darling_core/src/codegen/from_variant_impl.rs create mode 100644 vendor/darling_core/src/codegen/mod.rs create mode 100644 vendor/darling_core/src/codegen/outer_from_impl.rs create mode 100644 vendor/darling_core/src/codegen/trait_impl.rs create mode 100644 vendor/darling_core/src/codegen/variant.rs create mode 100644 vendor/darling_core/src/codegen/variant_data.rs create mode 100644 vendor/darling_core/src/derive.rs create mode 100644 vendor/darling_core/src/error/kind.rs create mode 100644 vendor/darling_core/src/error/mod.rs create mode 100644 vendor/darling_core/src/from_derive_input.rs create mode 100644 vendor/darling_core/src/from_field.rs create mode 100644 vendor/darling_core/src/from_generic_param.rs create mode 100644 vendor/darling_core/src/from_generics.rs create mode 100644 vendor/darling_core/src/from_meta.rs create mode 100644 vendor/darling_core/src/from_type_param.rs create mode 100644 vendor/darling_core/src/from_variant.rs create mode 100644 vendor/darling_core/src/lib.rs create mode 100644 vendor/darling_core/src/macros_private.rs create mode 100644 vendor/darling_core/src/macros_public.rs create mode 100644 vendor/darling_core/src/options/core.rs create mode 100644 vendor/darling_core/src/options/forward_attrs.rs create mode 100644 vendor/darling_core/src/options/from_derive.rs create mode 100644 vendor/darling_core/src/options/from_field.rs create mode 100644 vendor/darling_core/src/options/from_meta.rs create mode 100644 vendor/darling_core/src/options/from_type_param.rs create mode 100644 vendor/darling_core/src/options/from_variant.rs create mode 100644 vendor/darling_core/src/options/input_field.rs create mode 100644 vendor/darling_core/src/options/input_variant.rs create mode 100644 vendor/darling_core/src/options/mod.rs create mode 100644 vendor/darling_core/src/options/outer_from.rs create mode 100644 vendor/darling_core/src/options/shape.rs create mode 100644 vendor/darling_core/src/usage/generics_ext.rs create mode 100644 vendor/darling_core/src/usage/ident_set.rs create mode 100644 vendor/darling_core/src/usage/lifetimes.rs create mode 100644 vendor/darling_core/src/usage/mod.rs create mode 100644 vendor/darling_core/src/usage/options.rs create mode 100644 vendor/darling_core/src/usage/type_params.rs create mode 100644 vendor/darling_core/src/util/ident_list.rs create mode 100644 vendor/darling_core/src/util/ident_string.rs create mode 100644 vendor/darling_core/src/util/ignored.rs create mode 100644 vendor/darling_core/src/util/mod.rs create mode 100644 vendor/darling_core/src/util/over_ride.rs create mode 100644 vendor/darling_core/src/util/spanned_value.rs create mode 100644 vendor/darling_core/src/util/with_original.rs create mode 100644 vendor/darling_macro/.cargo-checksum.json rename vendor/{pulldown-cmark-0.1.2 => darling_macro}/Cargo.toml (53%) create mode 100644 vendor/darling_macro/LICENSE create mode 100644 vendor/darling_macro/src/lib.rs create mode 100644 vendor/env_logger/.cargo-checksum.json create mode 100644 vendor/env_logger/Cargo.toml rename vendor/{itertools-0.7.8 => env_logger}/LICENSE-APACHE (100%) rename vendor/{bitflags-0.9.1 => env_logger}/LICENSE-MIT (100%) create mode 100644 vendor/env_logger/README.md create mode 100644 vendor/env_logger/examples/custom_default_format.rs create mode 100644 vendor/env_logger/examples/custom_format.rs create mode 100644 vendor/env_logger/examples/custom_logger.rs create mode 100644 vendor/env_logger/examples/default.rs create mode 100644 vendor/env_logger/examples/direct_logger.rs create mode 100644 vendor/env_logger/src/filter/mod.rs create mode 100644 vendor/env_logger/src/filter/regex.rs create mode 100644 vendor/env_logger/src/filter/string.rs create mode 100644 vendor/env_logger/src/fmt/humantime/extern_impl.rs create mode 100644 vendor/env_logger/src/fmt/humantime/mod.rs create mode 100644 vendor/env_logger/src/fmt/humantime/shim_impl.rs create mode 100644 vendor/env_logger/src/fmt/mod.rs create mode 100644 vendor/env_logger/src/fmt/writer/atty.rs create mode 100644 vendor/env_logger/src/fmt/writer/mod.rs create mode 100644 vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs create mode 100644 vendor/env_logger/src/fmt/writer/termcolor/mod.rs create mode 100644 vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs create mode 100644 vendor/env_logger/src/lib.rs create mode 100644 vendor/env_logger/tests/init-twice-retains-filter.rs create mode 100644 vendor/env_logger/tests/log-in-log.rs create mode 100644 vendor/env_logger/tests/regexp_filter.rs create mode 100644 vendor/fnv/.cargo-checksum.json create mode 100644 vendor/fnv/Cargo.toml rename vendor/{rand-0.4.3 => fnv}/LICENSE-APACHE (100%) create mode 100644 vendor/fnv/LICENSE-MIT create mode 100644 vendor/fnv/README.md create mode 100644 vendor/fnv/lib.rs create mode 100644 vendor/fuchsia-cprng/.cargo-checksum.json create mode 100644 vendor/fuchsia-cprng/AUTHORS create mode 100644 vendor/fuchsia-cprng/Cargo.toml create mode 100644 vendor/fuchsia-cprng/LICENSE create mode 100644 vendor/fuchsia-cprng/PATENTS create mode 100644 vendor/fuchsia-cprng/src/lib.rs create mode 100644 vendor/html5ever/LICENSE-APACHE create mode 100644 vendor/html5ever/LICENSE-MIT create mode 100644 vendor/html5ever/benches/html5ever.rs delete mode 100644 vendor/html5ever/benches/tokenizer.rs create mode 100644 vendor/ident_case/.cargo-checksum.json create mode 100644 vendor/ident_case/CHANGELOG.md rename vendor/{bitflags-0.9.1 => ident_case}/Cargo.toml (53%) create mode 100644 vendor/ident_case/LICENSE create mode 100644 vendor/ident_case/README.md create mode 100644 vendor/ident_case/src/lib.rs create mode 100644 vendor/indexmap/.cargo-checksum.json create mode 100644 vendor/indexmap/Cargo.toml create mode 100644 vendor/indexmap/LICENSE-APACHE rename vendor/{itertools-0.7.8 => indexmap}/LICENSE-MIT (97%) create mode 100644 vendor/indexmap/README.rst create mode 100644 vendor/indexmap/benches/bench.rs create mode 100644 vendor/indexmap/benches/faststring.rs create mode 100644 vendor/indexmap/src/equivalent.rs create mode 100644 vendor/indexmap/src/lib.rs create mode 100644 vendor/indexmap/src/macros.rs create mode 100644 vendor/indexmap/src/map.rs create mode 100644 vendor/indexmap/src/mutable_keys.rs create mode 100644 vendor/indexmap/src/serde.rs create mode 100644 vendor/indexmap/src/set.rs create mode 100644 vendor/indexmap/src/util.rs create mode 100644 vendor/indexmap/tests/equivalent_trait.rs create mode 100644 vendor/indexmap/tests/quick.rs create mode 100644 vendor/indexmap/tests/serde.rs create mode 100644 vendor/indexmap/tests/tests.rs delete mode 100644 vendor/itertools-0.7.8/.cargo-checksum.json delete mode 100644 vendor/itertools-0.7.8/Cargo.toml delete mode 100644 vendor/itertools-0.7.8/Makefile delete mode 100644 vendor/itertools-0.7.8/README.rst delete mode 100644 vendor/itertools-0.7.8/benches/bench1.rs delete mode 100644 vendor/itertools-0.7.8/benches/extra/mod.rs delete mode 100644 vendor/itertools-0.7.8/benches/extra/zipslices.rs delete mode 100644 vendor/itertools-0.7.8/benches/tree_fold1.rs delete mode 100644 vendor/itertools-0.7.8/benches/tuple_combinations.rs delete mode 100644 vendor/itertools-0.7.8/benches/tuples.rs delete mode 100644 vendor/itertools-0.7.8/bors.toml delete mode 100644 vendor/itertools-0.7.8/custom.css delete mode 100644 vendor/itertools-0.7.8/examples/iris.data delete mode 100644 vendor/itertools-0.7.8/examples/iris.rs delete mode 100644 vendor/itertools-0.7.8/src/adaptors/mod.rs delete mode 100644 vendor/itertools-0.7.8/src/adaptors/multi_product.rs delete mode 100644 vendor/itertools-0.7.8/src/combinations.rs delete mode 100644 vendor/itertools-0.7.8/src/concat_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/cons_tuples_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/diff.rs delete mode 100644 vendor/itertools-0.7.8/src/either_or_both.rs delete mode 100644 vendor/itertools-0.7.8/src/format.rs delete mode 100644 vendor/itertools-0.7.8/src/free.rs delete mode 100644 vendor/itertools-0.7.8/src/group_map.rs delete mode 100644 vendor/itertools-0.7.8/src/groupbylazy.rs delete mode 100644 vendor/itertools-0.7.8/src/impl_macros.rs delete mode 100644 vendor/itertools-0.7.8/src/intersperse.rs delete mode 100644 vendor/itertools-0.7.8/src/kmerge_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/lib.rs delete mode 100644 vendor/itertools-0.7.8/src/merge_join.rs delete mode 100644 vendor/itertools-0.7.8/src/minmax.rs delete mode 100644 vendor/itertools-0.7.8/src/multipeek_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/pad_tail.rs delete mode 100644 vendor/itertools-0.7.8/src/peeking_take_while.rs delete mode 100644 vendor/itertools-0.7.8/src/process_results_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/put_back_n_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/rciter_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/repeatn.rs delete mode 100644 vendor/itertools-0.7.8/src/size_hint.rs delete mode 100644 vendor/itertools-0.7.8/src/sources.rs delete mode 100644 vendor/itertools-0.7.8/src/tee.rs delete mode 100644 vendor/itertools-0.7.8/src/tuple_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/unique_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/with_position.rs delete mode 100644 vendor/itertools-0.7.8/src/zip_eq_impl.rs delete mode 100644 vendor/itertools-0.7.8/src/zip_longest.rs delete mode 100644 vendor/itertools-0.7.8/src/ziptuple.rs delete mode 100644 vendor/itertools-0.7.8/tests/merge_join.rs delete mode 100644 vendor/itertools-0.7.8/tests/peeking_take_while.rs delete mode 100644 vendor/itertools-0.7.8/tests/quick.rs delete mode 100644 vendor/itertools-0.7.8/tests/test_core.rs delete mode 100644 vendor/itertools-0.7.8/tests/test_std.rs delete mode 100644 vendor/itertools-0.7.8/tests/tuples.rs delete mode 100644 vendor/itertools-0.7.8/tests/zip.rs create mode 100644 vendor/markup5ever/LICENSE-APACHE create mode 100644 vendor/markup5ever/LICENSE-MIT create mode 100644 vendor/mdbook/CHANGELOG.md delete mode 100644 vendor/mdbook/examples/de-emphasize.rs rename vendor/mdbook/tests/{alternate_backends.rs => alternative_backends.rs} (95%) create mode 100644 vendor/mdbook/tests/dummy_book/src/first/markdown.md create mode 100644 vendor/mdbook/tests/dummy_book/src/first/nested-test.rs rename vendor/proc-macro2/src/{stable.rs => fallback.rs} (93%) rename vendor/proc-macro2/src/{unstable.rs => wrapper.rs} (58%) delete mode 100644 vendor/pulldown-cmark-0.1.2/.cargo-checksum.json delete mode 100644 vendor/pulldown-cmark-0.1.2/CONTRIBUTING.md delete mode 100644 vendor/pulldown-cmark-0.1.2/README.md delete mode 100644 vendor/pulldown-cmark-0.1.2/build.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/specs/footnotes.txt delete mode 100644 vendor/pulldown-cmark-0.1.2/specs/table.txt delete mode 100644 vendor/pulldown-cmark-0.1.2/src/entities.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/escape.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/html.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/lib.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/main.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/parse.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/passes.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/puncttable.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/scanners.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/src/utils.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/tests/errors.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/tests/footnotes.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/tests/html.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/tests/spec.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/tests/table.rs delete mode 100644 vendor/pulldown-cmark-0.1.2/third_party/CommonMark/LICENSE delete mode 100644 vendor/pulldown-cmark-0.1.2/third_party/CommonMark/README.google delete mode 100644 vendor/pulldown-cmark-0.1.2/third_party/CommonMark/spec.txt delete mode 100644 vendor/pulldown-cmark-0.1.2/tools/mk_entities.py delete mode 100644 vendor/pulldown-cmark-0.1.2/tools/mk_puncttable.py create mode 100644 vendor/punycode/.cargo-checksum.json create mode 100644 vendor/punycode/Cargo.toml create mode 100644 vendor/punycode/LICENSE.md create mode 100644 vendor/punycode/src/bin/test_decode.rs create mode 100644 vendor/punycode/src/bin/test_encode.rs create mode 100644 vendor/punycode/src/lib.rs create mode 100644 vendor/quote/src/runtime.rs rename vendor/{rand-0.4.3 => rand-0.4.6}/.cargo-checksum.json (80%) rename vendor/{rand-0.4.3 => rand-0.4.6}/CHANGELOG.md (97%) rename vendor/{rand-0.4.3 => rand-0.4.6}/Cargo.toml (81%) create mode 100644 vendor/rand-0.4.6/LICENSE-APACHE rename vendor/{rand-0.4.3 => rand-0.4.6}/LICENSE-MIT (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/README.md (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/appveyor.yml (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/benches/bench.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/benches/distributions/exponential.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/benches/distributions/gamma.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/benches/distributions/mod.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/benches/distributions/normal.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/benches/generators.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/benches/misc.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/distributions/exponential.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/distributions/gamma.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/distributions/mod.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/distributions/normal.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/distributions/range.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/distributions/ziggurat_tables.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/jitter.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/lib.rs (99%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/os.rs (92%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/prng/chacha.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/prng/isaac.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/prng/isaac64.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/prng/mod.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/prng/xorshift.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/rand_impls.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/read.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/reseeding.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/src/seq.rs (100%) rename vendor/{rand-0.4.3 => rand-0.4.6}/utils/ziggurat_tables.py (100%) rename vendor/{rand_core => rand_core-0.3.0}/.cargo-checksum.json (100%) rename vendor/{rand_core => rand_core-0.3.0}/CHANGELOG.md (100%) rename vendor/{rand_core => rand_core-0.3.0}/COPYRIGHT (100%) rename vendor/{rand_core => rand_core-0.3.0}/Cargo.toml (100%) rename vendor/{rand_core => rand_core-0.3.0}/LICENSE-APACHE (100%) rename vendor/{rand_core => rand_core-0.3.0}/LICENSE-MIT (100%) rename vendor/{rand_core => rand_core-0.3.0}/README.md (100%) rename vendor/{rand_core => rand_core-0.3.0}/src/block.rs (100%) rename vendor/{rand_core => rand_core-0.3.0}/src/error.rs (100%) rename vendor/{rand_core => rand_core-0.3.0}/src/impls.rs (100%) rename vendor/{rand_core => rand_core-0.3.0}/src/le.rs (100%) rename vendor/{rand_core => rand_core-0.3.0}/src/lib.rs (100%) create mode 100644 vendor/rayon-core/src/compile_fail/mod.rs create mode 100644 vendor/rayon-core/src/compile_fail/quicksort_race1.rs create mode 100644 vendor/rayon-core/src/compile_fail/quicksort_race2.rs create mode 100644 vendor/rayon-core/src/compile_fail/quicksort_race3.rs create mode 100644 vendor/rayon-core/src/compile_fail/rc_return.rs create mode 100644 vendor/rayon-core/src/compile_fail/rc_upvar.rs create mode 100644 vendor/rayon-core/src/compile_fail/scope_join_bad.rs create mode 100644 vendor/rayon-core/tests/double_init_fail.rs create mode 100644 vendor/rayon-core/tests/init_zero_threads.rs create mode 100644 vendor/rayon-core/tests/scope_join.rs create mode 100644 vendor/rayon-core/tests/simple_panic.rs create mode 100644 vendor/rayon-core/tests/stack_overflow_crash.rs create mode 100644 vendor/rdrand/.cargo-checksum.json create mode 100644 vendor/rdrand/Cargo.toml create mode 100644 vendor/rdrand/LICENSE create mode 100644 vendor/rdrand/README.mkd create mode 100644 vendor/rdrand/appveyor.yml create mode 100644 vendor/rdrand/benches/rdrand.rs create mode 100644 vendor/rdrand/benches/rdseed.rs create mode 100644 vendor/rdrand/benches/std.rs create mode 100644 vendor/rdrand/src/changelog.rs create mode 100644 vendor/rdrand/src/lib.rs create mode 100644 vendor/rustc-demangle/src/legacy.rs create mode 100644 vendor/rustc-demangle/src/v0.rs create mode 100644 vendor/syn/build.rs create mode 100644 vendor/syn/src/custom_keyword.rs create mode 100644 vendor/syn/src/custom_punctuation.rs create mode 100644 vendor/syn/src/sealed.rs delete mode 100644 vendor/syn/src/synom.rs create mode 100644 vendor/toml-query_derive/.cargo-checksum.json create mode 100644 vendor/toml-query_derive/Cargo.toml create mode 100644 vendor/toml-query_derive/src/lib.rs create mode 100644 vendor/toml/.cargo-checksum.json create mode 100644 vendor/toml/Cargo.toml create mode 100644 vendor/toml/LICENSE-APACHE create mode 100644 vendor/toml/LICENSE-MIT create mode 100644 vendor/toml/README.md create mode 100644 vendor/toml/examples/decode.rs create mode 100644 vendor/toml/examples/enum_external.rs create mode 100644 vendor/toml/examples/toml2json.rs create mode 100644 vendor/toml/src/datetime.rs create mode 100644 vendor/toml/src/de.rs create mode 100644 vendor/toml/src/lib.rs create mode 100644 vendor/toml/src/macros.rs create mode 100644 vendor/toml/src/map.rs create mode 100644 vendor/toml/src/ser.rs create mode 100644 vendor/toml/src/spanned.rs create mode 100644 vendor/toml/src/tokens.rs create mode 100644 vendor/toml/src/value.rs create mode 100644 vendor/toml/tests/enum_external_deserialize.rs delete mode 100644 vendor/unreachable/.cargo-checksum.json delete mode 100644 vendor/unreachable/Cargo.toml delete mode 100644 vendor/unreachable/README.md delete mode 100644 vendor/unreachable/src/lib.rs delete mode 100644 vendor/void/.cargo-checksum.json delete mode 100644 vendor/void/Cargo.toml delete mode 100644 vendor/void/README.md delete mode 100644 vendor/void/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b687637a24..98dd10955d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,7 +25,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -33,7 +33,7 @@ dependencies = [ [[package]] name = "ammonia" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -44,6 +44,19 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ammonia" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "html5ever 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "annotate-snippets" version = "0.5.0" @@ -70,7 +83,7 @@ name = "arena" version = "0.0.0" dependencies = [ "rustc_data_structures 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -105,16 +118,23 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.11" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0", ] [[package]] @@ -123,24 +143,11 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] -[[package]] -name = "bit-set" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bit-vec" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "0.9.1" @@ -183,7 +190,7 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -206,7 +213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -253,15 +260,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.37.0" +version = "0.38.0" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo-test-macro 0.1.0", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.25.0", + "crates-io 0.26.0", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -272,18 +280,18 @@ dependencies = [ "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "git2-curl 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "git2-curl 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "im-rc 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -291,19 +299,19 @@ dependencies = [ "opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strip-ansi-escapes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -311,6 +319,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cargo-test-macro" +version = "0.1.0" +dependencies = [ + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cargo_metadata" version = "0.7.1" @@ -318,7 +334,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cargo_metadata" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -334,8 +362,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0", +] [[package]] name = "chalk-engine" @@ -383,7 +415,7 @@ dependencies = [ name = "clippy" version = "0.0.212" dependencies = [ - "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", "clippy_lints 0.0.212", "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -391,9 +423,9 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "rustc_tools_util 0.1.1", + "rustc_tools_util 0.2.0", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -404,8 +436,8 @@ version = "0.2.0" name = "clippy_lints" version = "0.0.212" dependencies = [ - "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "if_chain 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -413,9 +445,9 @@ dependencies = [ "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -462,7 +494,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -482,7 +514,7 @@ dependencies = [ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -501,7 +533,7 @@ dependencies = [ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -537,12 +569,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crates-io" -version = "0.25.0" +version = "0.26.0" dependencies = [ "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -561,7 +593,7 @@ name = "crc32fast" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -570,7 +602,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -597,7 +629,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -611,7 +643,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -623,7 +655,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -631,7 +663,7 @@ name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -676,6 +708,37 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "darling" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "darling_core 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "darling_macro 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "darling_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "darling_macro" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "darling_core 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "datafrog" version = "2.0.1" @@ -686,9 +749,9 @@ name = "derive-new" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -696,10 +759,10 @@ name = "derive_more" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -722,20 +785,31 @@ dependencies = [ [[package]] name = "directories" -version = "1.0.2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "dirs" -version = "1.0.4" +name = "dirs-sys" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -744,7 +818,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -761,21 +835,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ena" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ena" version = "0.13.0" @@ -813,7 +879,7 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -821,7 +887,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -836,7 +902,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -845,10 +911,10 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -861,7 +927,7 @@ name = "filetime" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -886,6 +952,9 @@ dependencies = [ [[package]] name = "fmt_macros" version = "0.0.0" +dependencies = [ + "syntax_pos 0.0.0", +] [[package]] name = "fnv" @@ -910,7 +979,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -936,6 +1005,11 @@ dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -956,7 +1030,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -991,12 +1065,12 @@ dependencies = [ [[package]] name = "git2" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1005,11 +1079,11 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1046,7 +1120,7 @@ dependencies = [ "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1061,9 +1135,8 @@ dependencies = [ "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1071,7 +1144,7 @@ name = "hashbrown" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-alloc 1.0.0", "rustc-std-workspace-core 1.0.0", ] @@ -1105,10 +1178,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "markup5ever 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "html5ever" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "markup5ever 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1118,7 +1204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1129,6 +1215,11 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "idna" version = "0.1.5" @@ -1141,7 +1232,7 @@ dependencies = [ [[package]] name = "if_chain" -version = "0.1.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1163,13 +1254,19 @@ dependencies = [ [[package]] name = "im-rc" -version = "12.3.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sized-chunks 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "installer" version = "0.0.0" @@ -1217,7 +1314,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1247,12 +1344,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "10.0.1" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1291,11 +1388,10 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.7.11" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1354,7 +1450,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1377,13 +1473,13 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.57.0" +version = "0.57.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1418,12 +1514,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "markup5ever" -version = "0.7.2" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "markup5ever" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1441,7 +1553,7 @@ name = "mdbook" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ammonia 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1455,7 +1567,7 @@ dependencies = [ "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1466,30 +1578,30 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ammonia 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "toml-query 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1621,13 +1733,14 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "directories 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1640,18 +1753,15 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "new_debug_unreachable" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "nodrop" @@ -1664,9 +1774,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1709,7 +1819,7 @@ version = "0.10.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1765,14 +1875,14 @@ name = "packed_simd" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1782,7 +1892,8 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", @@ -1805,7 +1916,7 @@ dependencies = [ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1853,9 +1964,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1900,7 +2011,7 @@ version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1952,7 +2063,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1967,29 +2078,10 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] -[[package]] -name = "proptest" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pulldown-cmark" version = "0.1.2" @@ -2010,6 +2102,11 @@ dependencies = [ "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "punycode" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quick-error" version = "1.2.2" @@ -2027,15 +2124,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.10" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "racer" -version = "2.1.22" +version = "2.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2046,16 +2143,18 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2091,6 +2190,11 @@ name = "rand_core" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rand_hc" version = "0.1.0" @@ -2107,6 +2211,19 @@ dependencies = [ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_pcg" version = "0.1.1" @@ -2130,19 +2247,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2160,12 +2284,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2227,10 +2351,10 @@ dependencies = [ [[package]] name = "rls" -version = "1.36.0" +version = "1.37.0" dependencies = [ - "cargo 0.37.0", - "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo 0.38.0", + "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2240,14 +2364,14 @@ dependencies = [ "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.57.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.57.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2259,9 +2383,9 @@ dependencies = [ "rls-vfs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 1.2.2", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_tools_util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 1.3.0", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2269,7 +2393,7 @@ dependencies = [ "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-process 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2286,7 +2410,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2301,7 +2425,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2313,7 +2437,7 @@ name = "rls-span" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2331,7 +2455,7 @@ version = "0.1.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "mdbook 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2339,7 +2463,7 @@ name = "rustc" version = "0.0.0" dependencies = [ "arena 0.0.0", - "backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2363,7 +2487,7 @@ dependencies = [ "rustc_target 0.0.0", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2371,20 +2495,21 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2394,95 +2519,114 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_macros" +version = "491.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-rustc_target" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "407.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.10" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2504,16 +2648,6 @@ dependencies = [ "rustc_target 0.0.0", ] -[[package]] -name = "rustc-rayon" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-rayon" version = "0.2.0" @@ -2524,17 +2658,6 @@ dependencies = [ "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-rayon-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-rayon-core" version = "0.2.0" @@ -2573,10 +2696,10 @@ dependencies = [ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2589,7 +2712,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2600,7 +2723,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2610,7 +2733,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2635,7 +2758,7 @@ dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_llvm 0.0.0", ] @@ -2652,7 +2775,7 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", "rustc_codegen_utils 0.0.0", @@ -2660,7 +2783,6 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_fs_util 0.0.0", "rustc_incremental 0.0.0", - "rustc_mir 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -2674,10 +2796,11 @@ version = "0.0.0" dependencies = [ "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_metadata 0.0.0", - "rustc_mir 0.0.0", "rustc_target 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", @@ -2696,9 +2819,10 @@ dependencies = [ name = "rustc_data_structures" version = "0.0.0" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2708,7 +2832,7 @@ dependencies = [ "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2742,7 +2866,7 @@ dependencies = [ "rustc_typeck 0.0.0", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_ext 0.0.0", "syntax_pos 0.0.0", @@ -2752,6 +2876,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ + "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", @@ -2806,7 +2931,7 @@ dependencies = [ "rustc_typeck 0.0.0", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_ext 0.0.0", "syntax_pos 0.0.0", @@ -2840,7 +2965,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2849,10 +2974,10 @@ name = "rustc_macros" version = "0.1.0" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2867,6 +2992,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_ext 0.0.0", @@ -2890,7 +3016,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2902,7 +3028,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2949,12 +3075,13 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_metadata 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2985,15 +3112,16 @@ dependencies = [ "rustc_cratesio_shim 0.0.0", "rustc_data_structures 0.0.0", "serialize 0.0.0", + "syntax_pos 0.0.0", ] [[package]] name = "rustc_tools_util" -version = "0.1.1" +version = "0.2.0" [[package]] name = "rustc_tools_util" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3007,7 +3135,7 @@ dependencies = [ "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -3019,7 +3147,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3033,7 +3161,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -3053,6 +3181,7 @@ dependencies = [ "minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3074,14 +3203,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustfmt-config_proc_macro" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustfmt-nightly" -version = "1.2.2" +version = "1.3.0" dependencies = [ "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3089,7 +3228,7 @@ dependencies = [ "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3098,31 +3237,21 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-config_proc_macro 0.1.0", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rusty-fork" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wait-timeout 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ryu" version = "0.2.7" @@ -3166,7 +3295,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3176,7 +3305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.82" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3187,9 +3316,9 @@ name = "serde_derive" version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3197,7 +3326,7 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3205,16 +3334,17 @@ name = "serde_json" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serialize" version = "0.0.0" dependencies = [ - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3252,6 +3382,14 @@ name = "siphasher" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sized-chunks" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" version = "0.4.2" @@ -3259,18 +3397,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "socket2" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3286,9 +3421,10 @@ name = "std" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3298,7 +3434,6 @@ dependencies = [ "panic_unwind 0.0.0", "profiler_builtins 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", "rustc_msan 0.0.0", @@ -3312,10 +3447,10 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3327,8 +3462,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3337,11 +3472,39 @@ name = "string_cache_shared" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strip-ansi-escapes" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "structopt" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "strum" version = "0.11.0" @@ -3353,9 +3516,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3370,11 +3533,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.22" +version = "0.15.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3388,12 +3551,12 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3410,7 +3573,7 @@ dependencies = [ "rustc_target 0.0.0", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax_pos 0.0.0", ] @@ -3423,7 +3586,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -3433,7 +3596,7 @@ name = "syntax_pos" version = "0.0.0" dependencies = [ "arena 0.0.0", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_macros 0.1.0", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3457,7 +3620,7 @@ name = "tempfile" version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3554,9 +3717,11 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3762,15 +3927,15 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3787,14 +3952,26 @@ dependencies = [ [[package]] name = "toml-query" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml-query_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml-query_derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "darling 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3858,14 +4035,6 @@ name = "unicode_categories" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "unstable-book-gen" version = "0.1.0" @@ -3879,7 +4048,8 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3899,7 +4069,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3913,6 +4083,11 @@ name = "utf8-ranges" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "utf8parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -3939,16 +4114,11 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wait-timeout" -version = "0.1.5" +name = "vte" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4041,7 +4211,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" -"checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477" +"checksum ammonia 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8b93ecb80665873703bf3b0a77f369c96b183d8e0afaf30a3ff5ff07dfc6409" +"checksum ammonia 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c799ecf1ad77acb48b643e2f45b12d60ee41576287fc575031aa020de88b8f45" "checksum annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8bcdcd5b291ce85a78f2b9d082a8de9676c12b1840d386d67bc5eea6f9d2b4e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6" @@ -4049,10 +4220,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "18b65ea1161bfb2dd6da6fade5edd4dbd08fba85012123dd333d2fd1b90b2782" +"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" +"checksum backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)" = "2d631cd7af21b7ff796293f1990104e3cdb606852863bac32f000c193aa35dfb" "checksum backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "6ea90dd7b012b3d1a2cb6bec16670a0db2c95d4e931e84f4047e0460c1b34c8d" -"checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a" -"checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" @@ -4066,8 +4236,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" "checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" +"checksum cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "929766d993a2fde7a0ae962ee82429069cd7b68839cd9375b98efd719df65d3a" "checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "89431bba4e6b7092fb5fcd00a6f6ca596c55cc26b2f1e6dcdd08a1f4933f66b2" "checksum chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a" "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" @@ -4077,7 +4248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "e3f235c329e5cb9fa3d2ca2cc36256ba9a7f23fa76e0f4db6f68c23b73b2ac69" +"checksum compiler_builtins 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e79ed19793c99771b386d76e08c3419409bb3d418b81a8b8afc73524247461cf" "checksum compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" @@ -4094,18 +4265,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" "checksum curl 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)" = "a85f2f95f2bd277d316d1aa8a477687ab4a6942258c7db7c89c187534669979c" "checksum curl-sys 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "9d91a0052d5b982887d8e829bee0faffc7218ea3c6ebd3d6c2c8f678a93c9a42" +"checksum darling 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9158d690bc62a3a57c3e45b85e4d50de2008b39345592c64efd79345c7e24be0" +"checksum darling_core 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d2a368589465391e127e10c9e3a08efc8df66fd49b87dc8524c764bbe7f2ef82" +"checksum darling_macro 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "244e8987bd4e174385240cde20a3657f607fb0797563c28255c353b5819a07b1" "checksum datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -"checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" -"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" +"checksum directories 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccc83e029c3cebb4c8155c644d34e3a070ccdb4ff90d369c74cd73f7cb3c984" +"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" "checksum dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f283302e035e61c23f2b86b3093e8c6273a4c3125742d6087e96ade001ca5e63" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455" -"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" "checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" @@ -4124,6 +4298,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" "checksum fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d94485a00b1827b861dd9d1a2cc9764f9044d4c535514c0760a5a2012ef3399f" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" @@ -4131,8 +4306,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" -"checksum git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" -"checksum git2-curl 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d58551e903ed7e2d6fe3a2f3c7efa3a784ec29b19d0fbb035aaf0497c183fbdd" +"checksum git2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "924b2e7d2986e625dcad89e8a429a7b3adee3c3d71e585f4a66c4f7e78715e31" +"checksum git2-curl 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f21f0550fd5d3f7c5adb94797fcd3d1002d7fc1fa349c82fe44f3c97ef80b62c" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" "checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd" @@ -4142,27 +4317,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff" "checksum html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c213fa6a618dc1da552f54f85cba74b05d8e883c92ec4e89067736938084c26e" +"checksum html5ever 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce65ac8028cf5a287a7dbf6c4e0a6cf2dcf022ed5b167a81bae66ebf599a8b7" "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" +"checksum if_chain 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d" "checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002" -"checksum im-rc 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9460397452f537fd51808056ff209f4c4c4c9d20d42ae952f517708726284972" +"checksum im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0197597d095c0d11107975d3175173f810ee572c2501ff4de64f4f3f119806" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bef0d4ce37578dfd80b466e3d8324bd9de788e249f1accebb0c472ea4b52bdc" "checksum jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b3d51e24009d966c8285d524dbaf6d60926636b2a89caee9ce0bd612494ddc16" "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" -"checksum jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a5152c3fda235dfd68341b3edf4121bc4428642c93acbd6de88c26bf95fc5d7" +"checksum jsonrpc-core 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "288dca7f9713710a29e485076b9340156cb701edb46a881f5d0c31aa4f5b9143" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" -"checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" +"checksum libgit2-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "941a41e23f77323b8c9d2ee118aec9ee39dfc176078c18b4757d3bad049d9ff7" "checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4" "checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" @@ -4170,15 +4348,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" "checksum lsp-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "169d737ad89cf8ddd82d1804d9122f54568c49377665157277cc90d747b1d31a" -"checksum lsp-types 0.57.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d220de1fbbb12b60df17898272579c22329375fc4baa960402fbd17cf0cdd165" +"checksum lsp-types 0.57.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b62b77309737b1e262b3bbf37ff8faa740562c633b14702afe9be85dbcb6f88a" "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" "checksum macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2c4deaccc2ead6a28c16c0ba82f07d52b6475397415ce40876e559b0b0ea510" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" -"checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475" +"checksum markup5ever 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "897636f9850c3eef4905a5540683ed53dc9393860f0846cab2c2ddf9939862ff" +"checksum markup5ever 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f1af46a727284117e09780d05038b1ce6fc9c76cc6df183c3dae5a8955a25e21" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f" -"checksum mdbook 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba0d44cb4089c741b9a91f3e5218298a40699c2f3a070a85014eed290c60819" +"checksum mdbook 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8e2c6442721202fb3b5800741aaafcc7076cdd199b326f0a39ce52a042cd37" "checksum measureme 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d09de7dafa3aa334bc806447c7e4de69419723312f4b88b80b561dea66601ce8" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" @@ -4193,7 +4372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" +"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" @@ -4228,28 +4407,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24f5844db2f839e97e3021980975f6ebf8691d9b9b2ca67ed3feb38dc3edb52c" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum pulldown-cmark 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "051e60ace841b3bfecd402fe5051c06cb3bec4a6e6fdd060a37aa8eb829a1db3" +"checksum punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ddd112cca70a4d30883b2d21568a1d376ff8be4758649f64f973c6845128ad3" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum racer 2.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4323343f25bc372dc9293ac6b5cd3034b32784af1e7de9366b4db71466d8c7" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" +"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" +"checksum racer 2.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "94dbdea3d959d8f76a2e303b3eadf107fd76da886b231291e649168613d432fb" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" "checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1" -"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" +"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" @@ -4260,26 +4442,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-data 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76c72ea97e045be5f6290bb157ebdc5ee9f2b093831ff72adfaf59025cf5c491" "checksum rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f1cb4694410d8d2ce43ccff3682f1c782158a018d5a9a92185675677f7533eb3" "checksum rls-vfs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce4b57b25b4330ed5ec14028fc02141e083ddafda327e7eb598dc0569c8c83c9" -"checksum rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5aab2fb5e5becf1c9183f6c63b8714817a3e780a20b4fe6b3920751c98a18225" -"checksum rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0235ff613d4f96176ea56748010b5d8e978605cc47856ba9bb5372f4f38e9c03" -"checksum rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e04a90b0dd8597da83633961698c61a2948f50c9d4b9a71e8afafc0ba0f158" -"checksum rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c03988d65fc5130787df32e8ea91738f78a8ed62b7a5bdd77f10e5cceb531d8e" -"checksum rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b33b9dc34f9fa50bf7e6fd14f2f3c1adc69833acf43c10f3e9795bd4d613712" -"checksum rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6de75caef2c7acba11994614266d60238653657677934817ab368d169333cba" -"checksum rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf09c60aaee892b0fd107544cfe607d8d463e7f33da34aa823566b8fd2b17f53" -"checksum rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69f38cc120ff317678bbda8c4f58c1bbc1de64b615383ab01480482dde5e95a1" -"checksum rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20a0a201141c5c416b1924b079eeefc7b013e34ece0740ce4997f358b3684a7f" -"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e" +"checksum rustc-ap-arena 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc0ad4318f3425229ed7b117275368b83269bec75f9609d4965dcb9752483c86" +"checksum rustc-ap-graphviz 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b80b7ea7902919f397c4bb12d102abe896fced7893d09d84bcac233e555bb388" +"checksum rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "752463d2b80039d23e42e667a9f6fe08213bd865f6ea301fb35f8068d94955ac" +"checksum rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c3d6a14181e11c132d0ef97a6c27e1bb1d4da09682d02222393875c10d1c364" +"checksum rustc-ap-rustc_errors 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55caea8426565de362e8df0df737e43b9f22d632e0e52710cbfe316acc6ce2f0" +"checksum rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "071420d762d2c779d1d4972356f37f5d049dcdd6c49e78f1b037e04c5a0f1a19" +"checksum rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5464696d0748e3019b9e5daca5fcadc53889dc2bca1dc26bf42001fd1c4194f" +"checksum rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9464445c11c15cf32ef27815b3ec89315b0ed73c6c771cbcf8543be59a3c1502" +"checksum rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff53245ae370d8e8073dc9cc13f8921e6110d0ccd208b64c388c5653fa6b9c83" +"checksum rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41896f0eb2eb2f4ddba406939aa6b07386160fa38bee8cde3f7f0d85663e3d47" +"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -"checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" -"checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108" "checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c5a95edfa0c893236ae4778bb7c4752760e4c0d245e19b5eff33c5aa5eb9dc" +"checksum rustc_tools_util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c21531a91512a4a51b490be6ba1c8eff34fdda0dc5bf87dc28d86748aac56" -"checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" @@ -4288,7 +4468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6" +"checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be" "checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" "checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" @@ -4297,20 +4477,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f272d1b7586bec132ed427f532dd418d8beca1ca7f2caf7df35569b1415a4b4" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" +"checksum sized-chunks 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2eb3fe454976eefb479f78f9b394d34d661b647c6326a3a6e66f68bb12c26" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" +"checksum strip-ansi-escapes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d63676e2abafa709460982ddc02a3bb586b6d15a49b75c212e06edd3933acee" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum structopt 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fa19a5a708e22bb5be31c1b6108a2a902f909c4b9ba85cba44c06632386bc0ff" +"checksum structopt-derive 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "c6d59d0ae8ef8de16e49e3ca7afa16024a3e0dfd974a75ef93fdc5464e34523f" "checksum strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e" "checksum strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8baacebd7b7c9b864d83a6ba7a246232983e277b86fa5cdec77f565715a4b136" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)" = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" @@ -4337,9 +4521,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c5890a989fa47ecdc7bcb4c63a77a82c18f306714104b1decfd722db17b39e" +"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" -"checksum toml-query 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab234a943a2363ad774020e2f9474a38a85bc4396bace01a96380144aef17db3" +"checksum toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a24369a1894ac8224efcfd567c3d141aea360292f49888e7ec7dcc316527aebb" +"checksum toml-query_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c99ca245ec273c7e75c8ee58f47b882d0146f3c2c8495158082c6671e8b5335" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" @@ -4351,17 +4536,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wait-timeout 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f3bf741a801531993db6478b95682117471f76916f5e690dd8d45395b09349" +"checksum vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" diff --git a/README.md b/README.md index 75d7823490..15d09f4aad 100644 --- a/README.md +++ b/README.md @@ -130,13 +130,12 @@ build. MSVC builds of Rust additionally require an installation of Visual Studio 2017 (or later) so `rustc` can use its linker. The simplest way is to get the -[Visual Studio Build Tools] and check the “C++ build tools” workload. +[Visual Studio], check the “C++ build tools” and “Windows 10 SDK” workload. -[Visual Studio Build Tools]: https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019 +[Visual Studio]: https://visualstudio.microsoft.com/downloads/ -At last check (cmake 3.14.3 and msvc 16.0.3) using the 2019 tools fails to -build the in-tree LLVM build with a CMake error, so use 2017 instead by -including the “MSVC v141 – VS 2017 C++ x64/x86 build tools (v14.16)” component. +(If you're installing cmake yourself, be careful that “C++ CMake tools for +Windows” doesn't get included under “Individual components”.) With these dependencies installed, you can build the compiler in a `cmd.exe` shell with: @@ -151,7 +150,7 @@ then you may need to force rustbuild to use an older version. This can be done by manually calling the appropriate vcvars file before running the bootstrap. ```batch -> CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" +> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" > python x.py build ``` diff --git a/RELEASES.md b/RELEASES.md index fcf42b5fcb..6049a8ef4c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,121 @@ +Version 1.37.0 (2019-08-15) +========================== + +Language +-------- +- `#[must_use]` will now warn if the type is contained in a [tuple][61100], + [`Box`][62228], or an [array][62235] and unused. +- [You can now use the `cfg` and `cfg_attr` attributes on + generic parameters.][61547] +- [You can now use enum variants through type alias.][61682] e.g. You can + write the following: + ```rust + type MyOption = Option; + + fn increment_or_zero(x: MyOption) -> u8 { + match x { + MyOption::Some(y) => y + 1, + MyOption::None => 0, + } + } + ``` +- [You can now use `_` as an identifier for consts.][61347] e.g. You can write + `const _: u32 = 5;`. +- [You can now use `#[repr(align(X)]` on enums.][61229] +- [The `?`/_"Kleene"_ macro operator is now available in the + 2015 edition.][60932] + +Compiler +-------- +- [You can now enable Profile-Guided Optimization with the `-C profile-generate` + and `-C profile-use` flags.][61268] For more information on how to use profile + guided optimization, please refer to the [rustc book][rustc-book-pgo]. +- [The `rust-lldb` wrapper script should now work again.][61827] + +Libraries +--------- +- [`mem::MaybeUninit` is now ABI-compatible with `T`.][61802] + +Stabilized APIs +--------------- +- [`BufReader::buffer`] +- [`BufWriter::buffer`] +- [`Cell::from_mut`] +- [`Cell<[T]>::as_slice_of_cells`][`Cell::as_slice_of_cells`] +- [`DoubleEndedIterator::nth_back`] +- [`Option::xor`] +- [`Wrapping::reverse_bits`] +- [`i128::reverse_bits`] +- [`i16::reverse_bits`] +- [`i32::reverse_bits`] +- [`i64::reverse_bits`] +- [`i8::reverse_bits`] +- [`isize::reverse_bits`] +- [`slice::copy_within`] +- [`u128::reverse_bits`] +- [`u16::reverse_bits`] +- [`u32::reverse_bits`] +- [`u64::reverse_bits`] +- [`u8::reverse_bits`] +- [`usize::reverse_bits`] + +Cargo +----- +- [`Cargo.lock` files are now included by default when publishing executable crates + with executables.][cargo/7026] +- [You can now specify `default-run="foo"` in `[package]` to specify the + default executable to use for `cargo run`.][cargo/7056] + +Misc +---- + +Compatibility Notes +------------------- +- [Using `...` for inclusive range patterns will now warn by default.][61342] + Please transition your code to using the `..=` syntax for inclusive + ranges instead. +- [Using a trait object without the `dyn` will now warn by default.][61203] + Please transition your code to use `dyn Trait` for trait objects instead. + +[62228]: https://github.com/rust-lang/rust/pull/62228/ +[62235]: https://github.com/rust-lang/rust/pull/62235/ +[61802]: https://github.com/rust-lang/rust/pull/61802/ +[61827]: https://github.com/rust-lang/rust/pull/61827/ +[61547]: https://github.com/rust-lang/rust/pull/61547/ +[61682]: https://github.com/rust-lang/rust/pull/61682/ +[61268]: https://github.com/rust-lang/rust/pull/61268/ +[61342]: https://github.com/rust-lang/rust/pull/61342/ +[61347]: https://github.com/rust-lang/rust/pull/61347/ +[61100]: https://github.com/rust-lang/rust/pull/61100/ +[61203]: https://github.com/rust-lang/rust/pull/61203/ +[61229]: https://github.com/rust-lang/rust/pull/61229/ +[60932]: https://github.com/rust-lang/rust/pull/60932/ +[cargo/7026]: https://github.com/rust-lang/cargo/pull/7026/ +[cargo/7056]: https://github.com/rust-lang/cargo/pull/7056/ +[`BufReader::buffer`]: https://doc.rust-lang.org/std/io/struct.BufReader.html#method.buffer +[`BufWriter::buffer`]: https://doc.rust-lang.org/std/io/struct.BufWriter.html#method.buffer +[`Cell::from_mut`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.from_mut +[`Cell::as_slice_of_cells`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_slice_of_cells +[`DoubleEndedIterator::nth_back`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.nth_back +[`Option::xor`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.xor +[`RefCell::try_borrow_unguarded`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.try_borrow_unguarded +[`Wrapping::reverse_bits`]: https://doc.rust-lang.org/std/num/struct.Wrapping.html#method.reverse_bits +[`i128::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i128.html#method.reverse_bits +[`i16::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i16.html#method.reverse_bits +[`i32::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i32.html#method.reverse_bits +[`i64::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i64.html#method.reverse_bits +[`i8::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i8.html#method.reverse_bits +[`isize::reverse_bits`]: https://doc.rust-lang.org/std/primitive.isize.html#method.reverse_bits +[`slice::copy_within`]: https://doc.rust-lang.org/std/primitive.slice.html#method.copy_within +[`u128::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u128.html#method.reverse_bits +[`u16::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u16.html#method.reverse_bits +[`u32::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u32.html#method.reverse_bits +[`u64::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u64.html#method.reverse_bits +[`u8::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u8.html#method.reverse_bits +[`usize::reverse_bits`]: https://doc.rust-lang.org/std/primitive.usize.html#method.reverse_bits +[rustc-book-pgo]: https://doc.rust-lang.org/rustc/profile-guided-optimization.html + + Version 1.36.0 (2019-07-04) ========================== @@ -261,7 +379,7 @@ Libraries produce a warning if their returning type is unused. - [The methods `checked_pow`, `saturating_pow`, `wrapping_pow`, and `overflowing_pow` are now available for all numeric types.][57873] These are - equivalvent to methods such as `wrapping_add` for the `pow` operation. + equivalent to methods such as `wrapping_add` for the `pow` operation. Stabilized APIs @@ -312,9 +430,9 @@ Misc Compatibility Notes ------------------- -- [`Command::before_exec` is now deprecated in favor of the - unsafe method `Command::pre_exec`.][58059] -- [Use of `ATOMIC_{BOOL, ISIZE, USIZE}_INIT` is now deprecated.][57425] As you +- [`Command::before_exec` is being replaced by the unsafe method + `Command::pre_exec`][58059] and will be deprecated with Rust 1.37.0. +- [Use of `ATOMIC_{BOOL, ISIZE, USIZE}_INIT` is now deprecated][57425] as you can now use `const` functions in `static` variables. [58370]: https://github.com/rust-lang/rust/pull/58370/ diff --git a/config.toml.example b/config.toml.example index 556625b531..c14adf8ce3 100644 --- a/config.toml.example +++ b/config.toml.example @@ -301,20 +301,27 @@ # library. #debug-assertions = false -# Whether or not debuginfo is emitted -#debuginfo = false +# Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`. +# `0` - no debug info +# `1` - line tables only +# `2` - full debug info with variable and type information +# Can be overriden for specific subsets of Rust code (rustc, std or tools). +# Debuginfo for tests run with compiletest is not controlled by this option +# and needs to be enabled separately with `debuginfo-level-tests`. +#debuginfo-level = if debug { 2 } else { 0 } -# Whether or not line number debug information is emitted -#debuginfo-lines = false +# Debuginfo level for the compiler. +#debuginfo-level-rustc = debuginfo-level -# Whether or not to only build debuginfo for the standard library if enabled. -# If enabled, this will not compile the compiler with debuginfo, just the -# standard library. -#debuginfo-only-std = false +# Debuginfo level for the standard library. +#debuginfo-level-std = debuginfo-level -# Enable debuginfo for the extended tools: cargo, rls, rustfmt -# Adding debuginfo makes them several times larger. -#debuginfo-tools = false +# Debuginfo level for the tools. +#debuginfo-level-tools = debuginfo-level + +# Debuginfo level for the test suites run with compiletest. +# FIXME(#61117): Some tests fail when this option is enabled. +#debuginfo-level-tests = 0 # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) #backtrace = true @@ -345,10 +352,8 @@ # harness are debuggable just from logfiles. #verbose-tests = false -# Flag indicating whether tests are compiled with optimizations (the -O flag) or -# with debuginfo (the -g flag) +# Flag indicating whether tests are compiled with optimizations (the -O flag). #optimize-tests = true -#debuginfo-tests = true # Flag indicating whether codegen tests will be run or not. If you get an error # saying that the FileCheck executable is missing, you may want to disable this. diff --git a/git-commit-hash b/git-commit-hash index aab6c2dea5..df8443341f 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -a53f9df32fbb0b5f4382caaad8f1a46f36ea887c \ No newline at end of file +eae3437dfe991621e8afdc82734f4a172d7ddf9b \ No newline at end of file diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 821c37dc23..595deb07ec 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -89,12 +89,31 @@ fn main() { let mut cmd = Command::new(rustc); cmd.args(&args) - .arg("--cfg") - .arg(format!("stage{}", stage)) .env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); let mut maybe_crate = None; + // Get the name of the crate we're compiling, if any. + let maybe_crate_name = args.windows(2) + .find(|a| &*a[0] == "--crate-name") + .map(|crate_name| &*crate_name[1]); + + if let Some(current_crate) = maybe_crate_name { + if let Some(target) = env::var_os("RUSTC_TIME") { + if target == "all" || + target.into_string().unwrap().split(",").any(|c| c.trim() == current_crate) + { + cmd.arg("-Ztime"); + } + } + } + + // Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift + // compiler libraries and such from stage 1 to 2. + if stage == "0" { + cmd.arg("--cfg").arg("bootstrap"); + } + // Print backtrace in case of ICE if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() { cmd.env("RUST_BACKTRACE", "1"); @@ -102,6 +121,10 @@ fn main() { cmd.env("RUSTC_BREAK_ON_ICE", "1"); + if let Ok(debuginfo_level) = env::var("RUSTC_DEBUGINFO_LEVEL") { + cmd.arg(format!("-Cdebuginfo={}", debuginfo_level)); + } + if let Some(target) = target { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option. @@ -144,10 +167,7 @@ fn main() { cmd.arg(format!("-Clinker={}", target_linker)); } - let crate_name = args.windows(2) - .find(|a| &*a[0] == "--crate-name") - .unwrap(); - let crate_name = &*crate_name[1]; + let crate_name = maybe_crate_name.unwrap(); maybe_crate = Some(crate_name); // If we're compiling specifically the `panic_abort` crate then we pass @@ -169,11 +189,6 @@ fn main() { // Set various options from config.toml to configure how we're building // code. - if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) { - cmd.arg("-g"); - } else if env::var("RUSTC_DEBUGINFO_LINES") == Ok("true".to_string()) { - cmd.arg("-Cdebuginfo=1"); - } let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") { Ok(s) => if s == "true" { "y" } else { "n" }, Err(..) => "n", diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 51663e9316..2e9df48d00 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -59,7 +59,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { const DEFAULT: bool = false; - /// Run this rule for all hosts without cross compiling. + /// If true, then this rule should be skipped if --target was specified, but --host was not const ONLY_HOSTS: bool = false; /// Primary function to execute this rule. Can call `builder.ensure()` @@ -163,7 +163,7 @@ impl StepDescription { // Determine the targets participating in this rule. let targets = if self.only_hosts { - if !builder.config.run_host_only { + if builder.config.skip_only_host_steps { return; // don't run anything } else { &builder.hosts @@ -318,6 +318,8 @@ impl<'a> ShouldRun<'a> { pub enum Kind { Build, Check, + Clippy, + Fix, Test, Bench, Dist, @@ -359,7 +361,7 @@ impl<'a> Builder<'a> { tool::Miri, native::Lld ), - Kind::Check => describe!( + Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, check::Test, check::Rustc, @@ -520,6 +522,8 @@ impl<'a> Builder<'a> { let (kind, paths) = match build.config.cmd { Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), Subcommand::Check { ref paths } => (Kind::Check, &paths[..]), + Subcommand::Clippy { ref paths } => (Kind::Clippy, &paths[..]), + Subcommand::Fix { ref paths } => (Kind::Fix, &paths[..]), Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]), Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), @@ -577,6 +581,30 @@ impl<'a> Builder<'a> { }) } + /// Similar to `compiler`, except handles the full-bootstrap option to + /// silently use the stage1 compiler instead of a stage2 compiler if one is + /// requested. + /// + /// Note that this does *not* have the side effect of creating + /// `compiler(stage, host)`, unlike `compiler` above which does have such + /// a side effect. The returned compiler here can only be used to compile + /// new artifacts, it can't be used to rely on the presence of a particular + /// sysroot. + /// + /// See `force_use_stage1` for documentation on what each argument is. + pub fn compiler_for( + &self, + stage: u32, + host: Interned, + target: Interned, + ) -> Compiler { + if self.build.force_use_stage1(Compiler { stage, host }, target) { + self.compiler(1, self.config.build) + } else { + self.compiler(stage, host) + } + } + pub fn sysroot(&self, compiler: Compiler) -> Interned { self.ensure(compile::Sysroot { compiler }) } @@ -750,24 +778,20 @@ impl<'a> Builder<'a> { // This is for the original compiler, but if we're forced to use stage 1, then // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since // we copy the libs forward. - let cmp = if self.force_use_stage1(compiler, target) { - self.compiler(1, compiler.host) - } else { - compiler - }; + let cmp = self.compiler_for(compiler.stage, compiler.host, target); let libstd_stamp = match cmd { - "check" => check::libstd_stamp(self, cmp, target), + "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target), _ => compile::libstd_stamp(self, cmp, target), }; let libtest_stamp = match cmd { - "check" => check::libtest_stamp(self, cmp, target), - _ => compile::libstd_stamp(self, cmp, target), + "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target), + _ => compile::libtest_stamp(self, cmp, target), }; let librustc_stamp = match cmd { - "check" => check::librustc_stamp(self, cmp, target), + "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target), _ => compile::librustc_stamp(self, cmp, target), }; @@ -831,9 +855,9 @@ impl<'a> Builder<'a> { assert_eq!(target, compiler.host); } - // Set a flag for `check` so that certain build scripts can do less work - // (e.g., not building/requiring LLVM). - if cmd == "check" { + // Set a flag for `check`/`clippy`/`fix`, so that certain build + // scripts can do less work (e.g. not building/requiring LLVM). + if cmd == "check" || cmd == "clippy" || cmd == "fix" { cargo.env("RUST_CHECK", "1"); } @@ -898,6 +922,11 @@ impl<'a> Builder<'a> { extra_args.push_str(&s); } + if cmd == "clippy" { + extra_args.push_str("-Zforce-unstable-if-unmarked -Zunstable-options \ + --json-rendered=termcolor"); + } + if !extra_args.is_empty() { cargo.env( "RUSTFLAGS", @@ -966,26 +995,19 @@ impl<'a> Builder<'a> { if let Some(ref error_format) = self.config.rustc_error_format { cargo.env("RUSTC_ERROR_FORMAT", error_format); } - if cmd != "build" && cmd != "check" && cmd != "rustc" && want_rustdoc { + if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); } - if mode.is_tool() { - // Tools like cargo and rls don't get debuginfo by default right now, but this can be - // enabled in the config. Adding debuginfo makes them several times larger. - if self.config.rust_debuginfo_tools { - cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()); - cargo.env( - "RUSTC_DEBUGINFO_LINES", - self.config.rust_debuginfo_lines.to_string(), - ); - } - } else { - cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()); - cargo.env( - "RUSTC_DEBUGINFO_LINES", - self.config.rust_debuginfo_lines.to_string(), - ); + let debuginfo_level = match mode { + Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc, + Mode::Std | Mode::Test => self.config.rust_debuginfo_level_std, + Mode::ToolBootstrap | Mode::ToolStd | + Mode::ToolTest | Mode::ToolRustc => self.config.rust_debuginfo_level_tools, + }; + cargo.env("RUSTC_DEBUGINFO_LEVEL", debuginfo_level.to_string()); + + if !mode.is_tool() { cargo.env("RUSTC_FORCE_UNSTABLE", "1"); // Currently the compiler depends on crates from crates.io, and @@ -1305,654 +1327,4 @@ impl<'a> Builder<'a> { } #[cfg(test)] -mod __test { - use super::*; - use crate::config::Config; - use std::thread; - - use pretty_assertions::assert_eq; - - fn configure(host: &[&str], target: &[&str]) -> Config { - let mut config = Config::default_opts(); - // don't save toolstates - config.save_toolstates = None; - config.run_host_only = true; - config.dry_run = true; - // try to avoid spurious failures in dist where we create/delete each others file - let dir = config.out.join("tmp-rustbuild-tests").join( - &thread::current() - .name() - .unwrap_or("unknown") - .replace(":", "-"), - ); - t!(fs::create_dir_all(&dir)); - config.out = dir; - config.build = INTERNER.intern_str("A"); - config.hosts = vec![config.build] - .clone() - .into_iter() - .chain(host.iter().map(|s| INTERNER.intern_str(s))) - .collect::>(); - config.targets = config - .hosts - .clone() - .into_iter() - .chain(target.iter().map(|s| INTERNER.intern_str(s))) - .collect::>(); - config - } - - fn first(v: Vec<(A, B)>) -> Vec { - v.into_iter().map(|(a, _)| a).collect::>() - } - - #[test] - fn dist_baseline() { - let build = Build::new(configure(&[], &[])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - - assert_eq!( - first(builder.cache.all::()), - &[dist::Docs { stage: 2, host: a },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - },] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_targets() { - let build = Build::new(configure(&[], &["B"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { stage: 2, host: a }, - dist::Docs { stage: 2, host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - },] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_hosts() { - let build = Build::new(configure(&["B"], &[])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { stage: 2, host: a }, - dist::Docs { stage: 2, host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_targets_and_hosts() { - let build = Build::new(configure(&["B"], &["C"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { stage: 2, host: a }, - dist::Docs { stage: 2, host: b }, - dist::Docs { stage: 2, host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Mingw { host: a }, - dist::Mingw { host: b }, - dist::Mingw { host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_target_flag() { - let mut config = configure(&["B"], &["C"]); - config.run_host_only = false; // as-if --target=C was passed - let build = Build::new(config); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { stage: 2, host: a }, - dist::Docs { stage: 2, host: b }, - dist::Docs { stage: 2, host: c }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Mingw { host: a }, - dist::Mingw { host: b }, - dist::Mingw { host: c }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[]); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[]); - } - - #[test] - fn dist_with_same_targets_and_hosts() { - let build = Build::new(configure(&["B"], &["B"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Docs { stage: 2, host: a }, - dist::Docs { stage: 2, host: b }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Rustc { - compiler: Compiler { host: a, stage: 2 } - }, - dist::Rustc { - compiler: Compiler { host: b, stage: 2 } - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - dist::Std { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - ] - ); - assert_eq!(first(builder.cache.all::()), &[dist::Src]); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Std { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Std { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Std { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Std { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Std { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Assemble { - target_compiler: Compiler { host: a, stage: 0 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 1 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 2 }, - }, - compile::Assemble { - target_compiler: Compiler { host: b, stage: 2 }, - }, - ] - ); - } - - #[test] - fn build_default() { - let build = Build::new(configure(&["B"], &["C"])); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert!(!builder.cache.all::().is_empty()); - assert!(!builder.cache.all::().is_empty()); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Rustc { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 0 }, - target: b, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Rustc { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - ] - ); - - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: c, - }, - ] - ); - } - - #[test] - fn build_with_target_flag() { - let mut config = configure(&["B"], &["C"]); - config.run_host_only = false; - let build = Build::new(config); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); - - assert!(!builder.cache.all::().is_empty()); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Assemble { - target_compiler: Compiler { host: a, stage: 0 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 1 }, - }, - compile::Assemble { - target_compiler: Compiler { host: b, stage: 1 }, - }, - compile::Assemble { - target_compiler: Compiler { host: a, stage: 2 }, - }, - compile::Assemble { - target_compiler: Compiler { host: b, stage: 2 }, - }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Rustc { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 0 }, - target: b, - }, - compile::Rustc { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - ] - ); - - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: a, - }, - compile::Test { - compiler: Compiler { host: a, stage: 0 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 1 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: b, - }, - compile::Test { - compiler: Compiler { host: a, stage: 2 }, - target: c, - }, - compile::Test { - compiler: Compiler { host: b, stage: 2 }, - target: c, - }, - ] - ); - } - - #[test] - fn test_with_no_doc_stage0() { - let mut config = configure(&[], &[]); - config.stage = Some(0); - config.cmd = Subcommand::Test { - paths: vec!["src/libstd".into()], - test_args: vec![], - rustc_args: vec![], - fail_fast: true, - doc_tests: DocTests::No, - bless: false, - compare_mode: None, - rustfix_coverage: false, - }; - - let build = Build::new(config); - let mut builder = Builder::new(&build); - - let host = INTERNER.intern_str("A"); - - builder.run_step_descriptions( - &[StepDescription::from::()], - &["src/libstd".into()], - ); - - // Ensure we don't build any compiler artifacts. - assert!(!builder.cache.contains::()); - assert_eq!( - first(builder.cache.all::()), - &[test::Crate { - compiler: Compiler { host, stage: 0 }, - target: host, - mode: Mode::Std, - test_kind: test::TestKind::Test, - krate: INTERNER.intern_str("std"), - },] - ); - } - - #[test] - fn test_exclude() { - let mut config = configure(&[], &[]); - config.exclude = vec![ - "src/test/run-pass".into(), - "src/tools/tidy".into(), - ]; - config.cmd = Subcommand::Test { - paths: Vec::new(), - test_args: Vec::new(), - rustc_args: Vec::new(), - fail_fast: true, - doc_tests: DocTests::No, - bless: false, - compare_mode: None, - rustfix_coverage: false, - }; - - let build = Build::new(config); - let builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]); - - // Ensure we have really excluded run-pass & tidy - assert!(!builder.cache.contains::()); - assert!(!builder.cache.contains::()); - - // Ensure other tests are not affected. - assert!(builder.cache.contains::()); - assert!(builder.cache.contains::()); - } -} +mod tests; diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs new file mode 100644 index 0000000000..cab7443bf3 --- /dev/null +++ b/src/bootstrap/builder/tests.rs @@ -0,0 +1,658 @@ +use super::*; +use crate::config::Config; +use std::thread; + +use pretty_assertions::assert_eq; + +fn configure(host: &[&str], target: &[&str]) -> Config { + let mut config = Config::default_opts(); + // don't save toolstates + config.save_toolstates = None; + config.skip_only_host_steps = false; + config.dry_run = true; + // try to avoid spurious failures in dist where we create/delete each others file + let dir = config.out.join("tmp-rustbuild-tests").join( + &thread::current() + .name() + .unwrap_or("unknown") + .replace(":", "-"), + ); + t!(fs::create_dir_all(&dir)); + config.out = dir; + config.build = INTERNER.intern_str("A"); + config.hosts = vec![config.build] + .clone() + .into_iter() + .chain(host.iter().map(|s| INTERNER.intern_str(s))) + .collect::>(); + config.targets = config + .hosts + .clone() + .into_iter() + .chain(target.iter().map(|s| INTERNER.intern_str(s))) + .collect::>(); + config +} + +fn first(v: Vec<(A, B)>) -> Vec { + v.into_iter().map(|(a, _)| a).collect::>() +} + +#[test] +fn dist_baseline() { + let build = Build::new(configure(&[], &[])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + + assert_eq!( + first(builder.cache.all::()), + &[dist::Docs { host: a },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + },] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_with_targets() { + let build = Build::new(configure(&[], &["B"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + },] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_with_hosts() { + let build = Build::new(configure(&["B"], &[])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_only_cross_host() { + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let mut build = Build::new(configure(&["B"], &[])); + build.config.docs = false; + build.config.extended = true; + build.hosts = vec![b]; + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); +} + +#[test] +fn dist_with_targets_and_hosts() { + let build = Build::new(configure(&["B"], &["C"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + dist::Docs { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); +} + +#[test] +fn dist_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.skip_only_host_steps = true; // as-if --target=C was passed + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + dist::Docs { host: c }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[]); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[]); +} + +#[test] +fn dist_with_same_targets_and_hosts() { + let build = Build::new(configure(&["B"], &["B"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Docs { host: a }, + dist::Docs { host: b }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[dist::Mingw { host: a }, dist::Mingw { host: b },] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Rustc { + compiler: Compiler { host: a, stage: 2 } + }, + dist::Rustc { + compiler: Compiler { host: b, stage: 2 } + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Std { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Assemble { + target_compiler: Compiler { host: a, stage: 0 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 1 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 2 }, + }, + compile::Assemble { + target_compiler: Compiler { host: b, stage: 2 }, + }, + ] + ); +} + +#[test] +fn build_default() { + let build = Build::new(configure(&["B"], &["C"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert!(!builder.cache.all::().is_empty()); + assert!(!builder.cache.all::().is_empty()); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + ] + ); + + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ] + ); +} + +#[test] +fn build_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.skip_only_host_steps = true; + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert!(!builder.cache.all::().is_empty()); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Assemble { + target_compiler: Compiler { host: a, stage: 0 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 1 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 2 }, + }, + compile::Assemble { + target_compiler: Compiler { host: b, stage: 2 }, + }, + ] + ); + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ] + ); + + assert_eq!( + first(builder.cache.all::()), + &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ] + ); +} + +#[test] +fn test_with_no_doc_stage0() { + let mut config = configure(&[], &[]); + config.stage = Some(0); + config.cmd = Subcommand::Test { + paths: vec!["src/libstd".into()], + test_args: vec![], + rustc_args: vec![], + fail_fast: true, + doc_tests: DocTests::No, + bless: false, + compare_mode: None, + rustfix_coverage: false, + pass: None, + }; + + let build = Build::new(config); + let mut builder = Builder::new(&build); + + let host = INTERNER.intern_str("A"); + + builder.run_step_descriptions( + &[StepDescription::from::()], + &["src/libstd".into()], + ); + + // Ensure we don't build any compiler artifacts. + assert!(!builder.cache.contains::()); + assert_eq!( + first(builder.cache.all::()), + &[test::Crate { + compiler: Compiler { host, stage: 0 }, + target: host, + mode: Mode::Std, + test_kind: test::TestKind::Test, + krate: INTERNER.intern_str("std"), + },] + ); +} + +#[test] +fn test_exclude() { + let mut config = configure(&[], &[]); + config.exclude = vec![ + "src/test/run-pass".into(), + "src/tools/tidy".into(), + ]; + config.cmd = Subcommand::Test { + paths: Vec::new(), + test_args: Vec::new(), + rustc_args: Vec::new(), + fail_fast: true, + doc_tests: DocTests::No, + bless: false, + compare_mode: None, + rustfix_coverage: false, + pass: None, + }; + + let build = Build::new(config); + let builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]); + + // Ensure we have really excluded run-pass & tidy + assert!(!builder.cache.contains::()); + assert!(!builder.cache.contains::()); + + // Ensure other tests are not affected. + assert!(builder.cache.contains::()); + assert!(builder.cache.contains::()); +} diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index dfc243b705..400375cd20 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -95,29 +95,39 @@ pub fn find(build: &mut Build) { }; build.cc.insert(target, compiler); - build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target))); - build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target, GitRepo::Rustc))); - if let Some(ar) = ar { - build.verbose(&format!("AR_{} = {:?}", &target, ar)); - build.ar.insert(target, ar); - } - } + let cflags = build.cflags(target, GitRepo::Rustc); - // For all host triples we need to find a C++ compiler as well - let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::>(); - for host in hosts.into_iter() { + // If we use llvm-libunwind, we will need a C++ compiler as well for all targets + // We'll need one anyways if the target triple is also a host triple let mut cfg = cc::Build::new(); cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false).cpp(true) - .target(&host).host(&build.build); - let config = build.config.target_config.get(&host); - if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { + .target(&target).host(&build.build); + + let cxx_configured = if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); + true + } else if build.hosts.contains(&target) || build.build == target { + set_compiler(&mut cfg, Language::CPlusPlus, target, config, build); + true } else { - set_compiler(&mut cfg, Language::CPlusPlus, host, config, build); + false + }; + + if cxx_configured { + let compiler = cfg.get_compiler(); + build.cxx.insert(target, compiler); + } + + build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target))); + build.verbose(&format!("CFLAGS_{} = {:?}", &target, cflags)); + if let Ok(cxx) = build.cxx(target) { + build.verbose(&format!("CXX_{} = {:?}", &target, cxx)); + build.verbose(&format!("CXXFLAGS_{} = {:?}", &target, cflags)); + } + if let Some(ar) = ar { + build.verbose(&format!("AR_{} = {:?}", &target, ar)); + build.ar.insert(target, ar); } - let compiler = cfg.get_compiler(); - build.verbose(&format!("CXX_{} = {:?}", host, compiler.path())); - build.cxx.insert(host, compiler); } } diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index a6da4f5385..41235d911c 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.36.0"; +pub const CFG_RELEASE_NUM: &str = "1.37.0"; pub struct GitInfo { inner: Option, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index a30b465698..bdf5306d4b 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1,8 +1,8 @@ -//! Implementation of compiling the compiler and standard library, in "check" mode. +//! Implementation of compiling the compiler and standard library, in "check"-based modes. use crate::compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; -use crate::builder::{RunConfig, Builder, ShouldRun, Step}; +use crate::builder::{RunConfig, Builder, Kind, ShouldRun, Step}; use crate::tool::{prepare_tool_cargo, SourceType}; use crate::{Compiler, Mode}; use crate::cache::{INTERNER, Interned}; @@ -13,6 +13,22 @@ pub struct Std { pub target: Interned, } +fn args(kind: Kind) -> Vec { + match kind { + Kind::Clippy => vec!["--".to_owned(), "--cap-lints".to_owned(), "warn".to_owned()], + _ => Vec::new() + } +} + +fn cargo_subcommand(kind: Kind) -> &'static str { + match kind { + Kind::Check => "check", + Kind::Clippy => "clippy", + Kind::Fix => "fix", + _ => unreachable!() + } +} + impl Step for Std { type Output = (); const DEFAULT: bool = true; @@ -31,13 +47,14 @@ impl Step for Std { let target = self.target; let compiler = builder.compiler(0, builder.config.build); - let mut cargo = builder.cargo(compiler, Mode::Std, target, "check"); + let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind)); std_cargo(builder, &compiler, target, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage)); builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + args(builder.kind), &libstd_stamp(builder, compiler, target), true); @@ -78,13 +95,15 @@ impl Step for Rustc { builder.ensure(Test { target }); - let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "check"); + let mut cargo = builder.cargo(compiler, Mode::Rustc, target, + cargo_subcommand(builder.kind)); rustc_cargo(builder, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage)); builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + args(builder.kind), &librustc_stamp(builder, compiler, target), true); @@ -127,7 +146,8 @@ impl Step for CodegenBackend { builder.ensure(Rustc { target }); - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "check"); + let mut cargo = builder.cargo(compiler, Mode::Codegen, target, + cargo_subcommand(builder.kind)); cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); rustc_cargo_env(builder, &mut cargo); @@ -136,6 +156,7 @@ impl Step for CodegenBackend { let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); run_cargo(builder, &mut cargo, + args(builder.kind), &codegen_backend_stamp(builder, compiler, target, backend), true); } @@ -166,13 +187,14 @@ impl Step for Test { builder.ensure(Std { target }); - let mut cargo = builder.cargo(compiler, Mode::Test, target, "check"); + let mut cargo = builder.cargo(compiler, Mode::Test, target, cargo_subcommand(builder.kind)); test_cargo(builder, &compiler, target, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage)); builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + args(builder.kind), &libtest_stamp(builder, compiler, target), true); @@ -212,7 +234,7 @@ impl Step for Rustdoc { compiler, Mode::ToolRustc, target, - "check", + cargo_subcommand(builder.kind), "src/tools/rustdoc", SourceType::InTree, &[]); @@ -221,6 +243,7 @@ impl Step for Rustdoc { println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target); run_cargo(builder, &mut cargo, + args(builder.kind), &rustdoc_stamp(builder, compiler, target), true); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index e1cdd226fd..576267e694 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -70,20 +70,20 @@ impl Step for Std { builder.ensure(StartupObjects { compiler, target }); - if builder.force_use_stage1(compiler, target) { - let from = builder.compiler(1, builder.config.build); + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + if compiler_to_use != compiler { builder.ensure(Std { - compiler: from, + compiler: compiler_to_use, target, }); - builder.info(&format!("Uplifting stage1 std ({} -> {})", from.host, target)); + builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target)); // Even if we're not building std this stage, the new sysroot must // still contain the third party objects needed by various targets. copy_third_party_objects(builder, &compiler, target); builder.ensure(StdLink { - compiler: from, + compiler: compiler_to_use, target_compiler: compiler, target, }); @@ -100,6 +100,7 @@ impl Step for Std { &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libstd_stamp(builder, compiler, target), false); @@ -161,7 +162,33 @@ pub fn std_cargo(builder: &Builder<'_>, cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } + // Determine if we're going to compile in optimized C intrinsics to + // the `compiler-builtins` crate. These intrinsics live in LLVM's + // `compiler-rt` repository, but our `src/llvm-project` submodule isn't + // always checked out, so we need to conditionally look for this. (e.g. if + // an external LLVM is used we skip the LLVM submodule checkout). + // + // Note that this shouldn't affect the correctness of `compiler-builtins`, + // but only its speed. Some intrinsics in C haven't been translated to Rust + // yet but that's pretty rare. Other intrinsics have optimized + // implementations in C which have only had slower versions ported to Rust, + // so we favor the C version where we can, but it's not critical. + // + // If `compiler-rt` is available ensure that the `c` feature of the + // `compiler-builtins` crate is enabled and it's configured to learn where + // `compiler-rt` is located. + let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); + let compiler_builtins_c_feature = if compiler_builtins_root.exists() { + cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root); + " compiler-builtins-c".to_string() + } else { + String::new() + }; + if builder.no_std(target) == Some(true) { + let mut features = "compiler-builtins-mem".to_string(); + features.push_str(&compiler_builtins_c_feature); + // for no-std targets we only compile a few no_std crates cargo .args(&["-p", "alloc"]) @@ -170,7 +197,8 @@ pub fn std_cargo(builder: &Builder<'_>, .arg("--features") .arg("compiler-builtins-mem compiler-builtins-c"); } else { - let features = builder.std_features(); + let mut features = builder.std_features(); + features.push_str(&compiler_builtins_c_feature); if compiler.stage != 0 && builder.config.sanitizers { // This variable is used by the sanitizer runtime crates, e.g. @@ -313,7 +341,7 @@ impl Step for StartupObjects { if !up_to_date(src_file, dst_file) { let mut cmd = Command::new(&builder.initial_rustc); builder.run(cmd.env("RUSTC_BOOTSTRAP", "1") - .arg("--cfg").arg("stage0") + .arg("--cfg").arg("bootstrap") .arg("--target").arg(target) .arg("--emit=obj") .arg("-o").arg(dst_file) @@ -375,15 +403,16 @@ impl Step for Test { return; } - if builder.force_use_stage1(compiler, target) { + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + if compiler_to_use != compiler { builder.ensure(Test { - compiler: builder.compiler(1, builder.config.build), + compiler: compiler_to_use, target, }); builder.info( &format!("Uplifting stage1 test ({} -> {})", builder.config.build, target)); builder.ensure(TestLink { - compiler: builder.compiler(1, builder.config.build), + compiler: compiler_to_use, target_compiler: compiler, target, }); @@ -398,6 +427,7 @@ impl Step for Test { &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libtest_stamp(builder, compiler, target), false); @@ -500,15 +530,16 @@ impl Step for Rustc { return; } - if builder.force_use_stage1(compiler, target) { + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + if compiler_to_use != compiler { builder.ensure(Rustc { - compiler: builder.compiler(1, builder.config.build), + compiler: compiler_to_use, target, }); builder.info(&format!("Uplifting stage1 rustc ({} -> {})", builder.config.build, target)); builder.ensure(RustcLink { - compiler: builder.compiler(1, builder.config.build), + compiler: compiler_to_use, target_compiler: compiler, target, }); @@ -529,6 +560,7 @@ impl Step for Rustc { compiler.stage, &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &librustc_stamp(builder, compiler, target), false); @@ -559,13 +591,6 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Command) { let libdir_relative = builder.config.libdir_relative().unwrap_or(Path::new("lib")); cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); - // If we're not building a compiler with debugging information then remove - // these two env vars which would be set otherwise. - if builder.config.rust_debuginfo_only_std { - cargo.env_remove("RUSTC_DEBUGINFO"); - cargo.env_remove("RUSTC_DEBUGINFO_LINES"); - } - if let Some(ref ver_date) = builder.rust_info.commit_date() { cargo.env("CFG_VER_DATE", ver_date); } @@ -664,9 +689,10 @@ impl Step for CodegenBackend { return; } - if builder.force_use_stage1(compiler, target) { + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + if compiler_to_use != compiler { builder.ensure(CodegenBackend { - compiler: builder.compiler(1, builder.config.build), + compiler: compiler_to_use, target, backend, }); @@ -687,6 +713,7 @@ impl Step for CodegenBackend { let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); let files = run_cargo(builder, cargo.arg("--features").arg(features), + vec![], &tmp_stamp, false); if builder.config.dry_run { @@ -748,6 +775,10 @@ pub fn build_codegen_backend(builder: &Builder<'_>, cargo.env("CFG_LLVM_ROOT", s); } } + // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm. + if let Some(ref s) = builder.config.llvm_ldflags { + cargo.env("LLVM_LINKER_FLAGS", s); + } // Building with a static libstdc++ is only supported on linux right now, // not for MSVC or macOS if builder.config.llvm_static_stdcpp && @@ -1057,6 +1088,7 @@ pub fn add_to_sysroot( pub fn run_cargo(builder: &Builder<'_>, cargo: &mut Command, + tail_args: Vec, stamp: &Path, is_check: bool) -> Vec @@ -1079,7 +1111,7 @@ pub fn run_cargo(builder: &Builder<'_>, // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let ok = stream_cargo(builder, cargo, &mut |msg| { + let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| { let (filenames, crate_types) = match msg { CargoMessage::CompilerArtifact { filenames, @@ -1088,6 +1120,10 @@ pub fn run_cargo(builder: &Builder<'_>, }, .. } => (filenames, crate_types), + CargoMessage::CompilerMessage { message } => { + eprintln!("{}", message.rendered); + return; + } _ => return, }; for filename in filenames { @@ -1215,6 +1251,7 @@ pub fn run_cargo(builder: &Builder<'_>, pub fn stream_cargo( builder: &Builder<'_>, cargo: &mut Command, + tail_args: Vec, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { if builder.config.dry_run { @@ -1225,6 +1262,10 @@ pub fn stream_cargo( cargo.arg("--message-format").arg("json") .stdout(Stdio::piped()); + for arg in tail_args { + cargo.arg(arg); + } + builder.verbose(&format!("running: {:?}", cargo)); let mut child = match cargo.spawn() { Ok(child) => child, @@ -1271,5 +1312,13 @@ pub enum CargoMessage<'a> { }, BuildScriptExecuted { package_id: Cow<'a, str>, + }, + CompilerMessage { + message: ClippyMessage<'a> } } + +#[derive(Deserialize)] +pub struct ClippyMessage<'a> { + rendered: Cow<'a, str>, +} diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index b1d009a674..66f504ea92 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -11,7 +11,6 @@ use std::process; use std::cmp; use build_helper::t; -use num_cpus; use toml; use serde::Deserialize; use crate::cache::{INTERNER, Interned}; @@ -52,7 +51,7 @@ pub struct Config { pub test_compare_mode: bool, pub llvm_libunwind: bool, - pub run_host_only: bool, + pub skip_only_host_steps: bool, pub on_fail: Option, pub stage: Option, @@ -96,15 +95,14 @@ pub struct Config { pub rust_codegen_units: Option, pub rust_codegen_units_std: Option, pub rust_debug_assertions: bool, - pub rust_debuginfo: bool, - pub rust_debuginfo_lines: bool, - pub rust_debuginfo_only_std: bool, - pub rust_debuginfo_tools: bool, + pub rust_debuginfo_level_rustc: u32, + pub rust_debuginfo_level_std: u32, + pub rust_debuginfo_level_tools: u32, + pub rust_debuginfo_level_tests: u32, pub rust_rpath: bool, pub rustc_parallel: bool, pub rustc_default_linker: Option, pub rust_optimize_tests: bool, - pub rust_debuginfo_tests: bool, pub rust_dist_src: bool, pub rust_codegen_backends: Vec>, pub rust_codegen_backends_dir: String, @@ -300,10 +298,11 @@ struct Rust { codegen_units: Option, codegen_units_std: Option, debug_assertions: Option, - debuginfo: Option, - debuginfo_lines: Option, - debuginfo_only_std: Option, - debuginfo_tools: Option, + debuginfo_level: Option, + debuginfo_level_rustc: Option, + debuginfo_level_std: Option, + debuginfo_level_tools: Option, + debuginfo_level_tests: Option, parallel_compiler: Option, backtrace: Option, default_linker: Option, @@ -311,7 +310,6 @@ struct Rust { musl_root: Option, rpath: Option, optimize_tests: Option, - debuginfo_tests: Option, codegen_tests: Option, ignore_git: Option, debug: Option, @@ -402,7 +400,7 @@ impl Config { config.rustc_error_format = flags.rustc_error_format; config.on_fail = flags.on_fail; config.stage = flags.stage; - config.jobs = flags.jobs; + config.jobs = flags.jobs.map(threads_from_config); config.cmd = flags.cmd; config.incremental = flags.incremental; config.dry_run = flags.dry_run; @@ -418,7 +416,9 @@ impl Config { } // If --target was specified but --host wasn't specified, don't run any host-only tests. - config.run_host_only = !(flags.host.is_empty() && !flags.target.is_empty()); + let has_hosts = !flags.host.is_empty(); + let has_targets = !flags.target.is_empty(); + config.skip_only_host_steps = !has_hosts && has_targets; let toml = file.map(|file| { let contents = t!(fs::read_to_string(&file)); @@ -495,12 +495,13 @@ impl Config { // Store off these values as options because if they're not provided // we'll infer default values for them later let mut llvm_assertions = None; - let mut debuginfo_lines = None; - let mut debuginfo_only_std = None; - let mut debuginfo_tools = None; let mut debug = None; - let mut debuginfo = None; let mut debug_assertions = None; + let mut debuginfo_level = None; + let mut debuginfo_level_rustc = None; + let mut debuginfo_level_std = None; + let mut debuginfo_level_tools = None; + let mut debuginfo_level_tests = None; let mut optimize = None; let mut ignore_git = None; @@ -540,14 +541,14 @@ impl Config { if let Some(ref rust) = toml.rust { debug = rust.debug; debug_assertions = rust.debug_assertions; - debuginfo = rust.debuginfo; - debuginfo_lines = rust.debuginfo_lines; - debuginfo_only_std = rust.debuginfo_only_std; - debuginfo_tools = rust.debuginfo_tools; + debuginfo_level = rust.debuginfo_level; + debuginfo_level_rustc = rust.debuginfo_level_rustc; + debuginfo_level_std = rust.debuginfo_level_std; + debuginfo_level_tools = rust.debuginfo_level_tools; + debuginfo_level_tests = rust.debuginfo_level_tests; optimize = rust.optimize; ignore_git = rust.ignore_git; set(&mut config.rust_optimize_tests, rust.optimize_tests); - set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests); set(&mut config.codegen_tests, rust.codegen_tests); set(&mut config.rust_rpath, rust.rpath); set(&mut config.jemalloc, rust.jemalloc); @@ -583,13 +584,8 @@ impl Config { set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone()); - match rust.codegen_units { - Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32), - Some(n) => config.rust_codegen_units = Some(n), - None => {} - } - - config.rust_codegen_units_std = rust.codegen_units_std; + config.rust_codegen_units = rust.codegen_units.map(threads_from_config); + config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); } if let Some(ref t) = toml.target { @@ -639,18 +635,19 @@ impl Config { let default = true; config.rust_optimize = optimize.unwrap_or(default); - let default = match &config.channel[..] { - "stable" | "beta" | "nightly" => true, - _ => false, - }; - config.rust_debuginfo_lines = debuginfo_lines.unwrap_or(default); - config.rust_debuginfo_only_std = debuginfo_only_std.unwrap_or(default); - config.rust_debuginfo_tools = debuginfo_tools.unwrap_or(false); - let default = debug == Some(true); - config.rust_debuginfo = debuginfo.unwrap_or(default); config.rust_debug_assertions = debug_assertions.unwrap_or(default); + let with_defaults = |debuginfo_level_specific: Option| { + debuginfo_level_specific + .or(debuginfo_level) + .unwrap_or(if debug == Some(true) { 2 } else { 0 }) + }; + config.rust_debuginfo_level_rustc = with_defaults(debuginfo_level_rustc); + config.rust_debuginfo_level_std = with_defaults(debuginfo_level_std); + config.rust_debuginfo_level_tools = with_defaults(debuginfo_level_tools); + config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(0); + let default = config.channel == "dev"; config.ignore_git = ignore_git.unwrap_or(default); @@ -687,3 +684,10 @@ fn set(field: &mut T, val: Option) { *field = v; } } + +fn threads_from_config(v: u32) -> u32 { + match v { + 0 => num_cpus::get() as u32, + n => n, + } +} diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index ade8afee7c..907983d43a 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -37,7 +37,6 @@ o("compiler-docs", "build.compiler-docs", "build compiler documentation") o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") o("parallel-compiler", "rust.parallel-compiler", "build a multi-threaded rustc") o("test-miri", "rust.test-miri", "run miri's test suite") -o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata") o("verbose-tests", "rust.verbose-tests", "enable verbose output when running tests") o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds") o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds") @@ -77,10 +76,11 @@ o("optimize-llvm", "llvm.optimize", "build optimized LLVM") o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata") -o("debuginfo", "rust.debuginfo", "build with debugger metadata") -o("debuginfo-lines", "rust.debuginfo-lines", "build with line number debugger metadata") -o("debuginfo-only-std", "rust.debuginfo-only-std", "build only libstd with debugging information") -o("debuginfo-tools", "rust.debuginfo-tools", "build extended tools with debugging information") +v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code") +v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler") +v("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library") +v("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools") +v("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest") v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file") v("prefix", "install.prefix", "set installation prefix") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index b0616ff669..45bc77ec97 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -68,7 +68,6 @@ fn missing_tool(tool_name: &str, skip: bool) { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Docs { - pub stage: u32, pub host: Interned, } @@ -82,7 +81,6 @@ impl Step for Docs { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Docs { - stage: run.builder.top_stage, host: run.target, }); } @@ -130,7 +128,6 @@ impl Step for Docs { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustcDocs { - pub stage: u32, pub host: Interned, } @@ -144,7 +141,6 @@ impl Step for RustcDocs { fn make_run(run: RunConfig<'_>) { run.builder.ensure(RustcDocs { - stage: run.builder.top_stage, host: run.target, }); } @@ -647,7 +643,11 @@ impl Step for Std { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Std { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), target: run.target, }); } @@ -737,7 +737,14 @@ impl Step for Analysis { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Analysis { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), + // Find the actual compiler (handling the full bootstrap option) which + // produced the save-analysis data because that data isn't copied + // through the sysroot uplifting. + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), target: run.target, }); } @@ -757,14 +764,6 @@ impl Step for Analysis { builder.ensure(Std { compiler, target }); - // Package save-analysis from stage1 if not doing a full bootstrap, as the - // stage2 artifacts is simply copied from stage1 in that case. - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler.clone() - }; - let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let src = builder.stage_out(compiler, Mode::Std) @@ -805,6 +804,7 @@ fn copy_src_dirs(builder: &Builder<'_>, src_dirs: &[&str], exclude_dirs: &[&str] const LLVM_PROJECTS: &[&str] = &[ "llvm-project/clang", "llvm-project\\clang", + "llvm-project/libunwind", "llvm-project\\libunwind", "llvm-project/lld", "llvm-project\\lld", "llvm-project/lldb", "llvm-project\\lldb", "llvm-project/llvm", "llvm-project\\llvm", @@ -1066,7 +1066,7 @@ pub fn sanitize_sh(path: &Path) -> String { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Cargo { - pub stage: u32, + pub compiler: Compiler, pub target: Interned, } @@ -1080,16 +1080,20 @@ impl Step for Cargo { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Cargo { - stage: run.builder.top_stage, + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> PathBuf { - let stage = self.stage; + let compiler = self.compiler; let target = self.target; - builder.info(&format!("Dist cargo stage{} ({})", stage, target)); + builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/cargo"); let etc = src.join("src/etc"); let release_num = builder.release_num("cargo"); @@ -1104,10 +1108,7 @@ impl Step for Cargo { // Prepare the image directory builder.create_dir(&image.join("share/zsh/site-functions")); builder.create_dir(&image.join("etc/bash_completion.d")); - let cargo = builder.ensure(tool::Cargo { - compiler: builder.compiler(stage, builder.config.build), - target - }); + let cargo = builder.ensure(tool::Cargo { compiler, target }); builder.install(&cargo, &image.join("bin"), 0o755); for man in t!(etc.join("man").read_dir()) { let man = t!(man); @@ -1152,7 +1153,7 @@ impl Step for Cargo { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rls { - pub stage: u32, + pub compiler: Compiler, pub target: Interned, } @@ -1166,17 +1167,21 @@ impl Step for Rls { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Rls { - stage: run.builder.top_stage, + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { - let stage = self.stage; + let compiler = self.compiler; let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist RLS stage{} ({})", stage, target)); + builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/rls"); let release_num = builder.release_num("rls"); let name = pkgname(builder, "rls"); @@ -1191,8 +1196,9 @@ impl Step for Rls { // We expect RLS to build, because we've exited this step above if tool // state for RLS isn't testing. let rls = builder.ensure(tool::Rls { - compiler: builder.compiler(stage, builder.config.build), - target, extra_features: Vec::new() + compiler, + target, + extra_features: Vec::new(), }).or_else(|| { missing_tool("RLS", builder.build.config.missing_tools); None })?; builder.install(&rls, &image.join("bin"), 0o755); @@ -1231,7 +1237,7 @@ impl Step for Rls { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Clippy { - pub stage: u32, + pub compiler: Compiler, pub target: Interned, } @@ -1245,17 +1251,21 @@ impl Step for Clippy { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Clippy { - stage: run.builder.top_stage, + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { - let stage = self.stage; + let compiler = self.compiler; let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist clippy stage{} ({})", stage, target)); + builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/clippy"); let release_num = builder.release_num("clippy"); let name = pkgname(builder, "clippy"); @@ -1270,11 +1280,12 @@ impl Step for Clippy { // We expect clippy to build, because we've exited this step above if tool // state for clippy isn't testing. let clippy = builder.ensure(tool::Clippy { - compiler: builder.compiler(stage, builder.config.build), - target, extra_features: Vec::new() + compiler, + target, + extra_features: Vec::new(), }).or_else(|| { missing_tool("clippy", builder.build.config.missing_tools); None })?; let cargoclippy = builder.ensure(tool::CargoClippy { - compiler: builder.compiler(stage, builder.config.build), + compiler, target, extra_features: Vec::new() }).or_else(|| { missing_tool("cargo clippy", builder.build.config.missing_tools); None })?; @@ -1315,7 +1326,7 @@ impl Step for Clippy { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Miri { - pub stage: u32, + pub compiler: Compiler, pub target: Interned, } @@ -1329,17 +1340,21 @@ impl Step for Miri { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Miri { - stage: run.builder.top_stage, + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { - let stage = self.stage; + let compiler = self.compiler; let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist miri stage{} ({})", stage, target)); + builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/miri"); let release_num = builder.release_num("miri"); let name = pkgname(builder, "miri"); @@ -1354,12 +1369,14 @@ impl Step for Miri { // We expect miri to build, because we've exited this step above if tool // state for miri isn't testing. let miri = builder.ensure(tool::Miri { - compiler: builder.compiler(stage, builder.config.build), - target, extra_features: Vec::new() + compiler, + target, + extra_features: Vec::new(), }).or_else(|| { missing_tool("miri", builder.build.config.missing_tools); None })?; let cargomiri = builder.ensure(tool::CargoMiri { - compiler: builder.compiler(stage, builder.config.build), - target, extra_features: Vec::new() + compiler, + target, + extra_features: Vec::new() }).or_else(|| { missing_tool("cargo miri", builder.build.config.missing_tools); None })?; builder.install(&miri, &image.join("bin"), 0o755); @@ -1399,7 +1416,7 @@ impl Step for Miri { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustfmt { - pub stage: u32, + pub compiler: Compiler, pub target: Interned, } @@ -1413,16 +1430,20 @@ impl Step for Rustfmt { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Rustfmt { - stage: run.builder.top_stage, + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { - let stage = self.stage; + let compiler = self.compiler; let target = self.target; - builder.info(&format!("Dist Rustfmt stage{} ({})", stage, target)); + builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/rustfmt"); let release_num = builder.release_num("rustfmt"); let name = pkgname(builder, "rustfmt"); @@ -1435,12 +1456,14 @@ impl Step for Rustfmt { // Prepare the image directory let rustfmt = builder.ensure(tool::Rustfmt { - compiler: builder.compiler(stage, builder.config.build), - target, extra_features: Vec::new() + compiler, + target, + extra_features: Vec::new(), }).or_else(|| { missing_tool("Rustfmt", builder.build.config.missing_tools); None })?; let cargofmt = builder.ensure(tool::Cargofmt { - compiler: builder.compiler(stage, builder.config.build), - target, extra_features: Vec::new() + compiler, + target, + extra_features: Vec::new(), }).or_else(|| { missing_tool("Cargofmt", builder.build.config.missing_tools); None })?; builder.install(&rustfmt, &image.join("bin"), 0o755); @@ -1505,30 +1528,28 @@ impl Step for Extended { /// Creates a combined installer for the specified target in the provided stage. fn run(self, builder: &Builder<'_>) { - let stage = self.stage; let target = self.target; + let stage = self.stage; + let compiler = builder.compiler_for(self.stage, self.host, self.target); - builder.info(&format!("Dist extended stage{} ({})", stage, target)); + builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target)); let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target), }); - let cargo_installer = builder.ensure(Cargo { stage, target }); - let rustfmt_installer = builder.ensure(Rustfmt { stage, target }); - let rls_installer = builder.ensure(Rls { stage, target }); - let llvm_tools_installer = builder.ensure(LlvmTools { stage, target }); - let clippy_installer = builder.ensure(Clippy { stage, target }); - let miri_installer = builder.ensure(Miri { stage, target }); + let cargo_installer = builder.ensure(Cargo { compiler, target }); + let rustfmt_installer = builder.ensure(Rustfmt { compiler, target }); + let rls_installer = builder.ensure(Rls { compiler, target }); + let llvm_tools_installer = builder.ensure(LlvmTools { target }); + let clippy_installer = builder.ensure(Clippy { compiler, target }); + let miri_installer = builder.ensure(Miri { compiler, target }); let lldb_installer = builder.ensure(Lldb { target }); let mingw_installer = builder.ensure(Mingw { host: target }); - let analysis_installer = builder.ensure(Analysis { - compiler: builder.compiler(stage, self.host), - target - }); + let analysis_installer = builder.ensure(Analysis { compiler, target }); - let docs_installer = builder.ensure(Docs { stage, host: target, }); + let docs_installer = builder.ensure(Docs { host: target, }); let std_installer = builder.ensure(Std { - compiler: builder.compiler(stage, self.host), + compiler: builder.compiler(stage, target), target, }); @@ -2076,7 +2097,6 @@ pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct LlvmTools { - pub stage: u32, pub target: Interned, } @@ -2090,26 +2110,24 @@ impl Step for LlvmTools { fn make_run(run: RunConfig<'_>) { run.builder.ensure(LlvmTools { - stage: run.builder.top_stage, target: run.target, }); } fn run(self, builder: &Builder<'_>) -> Option { - let stage = self.stage; let target = self.target; assert!(builder.config.extended); /* run only if llvm-config isn't used */ if let Some(config) = builder.config.target_config.get(&target) { if let Some(ref _s) = config.llvm_config { - builder.info(&format!("Skipping LlvmTools stage{} ({}): external LLVM", - stage, target)); + builder.info(&format!("Skipping LlvmTools ({}): external LLVM", + target)); return None; } } - builder.info(&format!("Dist LlvmTools stage{} ({})", stage, target)); + builder.info(&format!("Dist LlvmTools ({})", target)); let src = builder.src.join("src/llvm-project/llvm"); let name = pkgname(builder, "llvm-tools"); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 9c3a17bff6..2969bbf5b0 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -46,10 +46,11 @@ macro_rules! book { } fn run(self, builder: &Builder<'_>) { - builder.ensure(Rustbook { + builder.ensure(RustbookSrc { target: self.target, name: INTERNER.intern_str($book_name), version: $book_ver, + src: doc_src(builder), }) } } @@ -60,50 +61,23 @@ macro_rules! book { // NOTE: When adding a book here, make sure to ALSO build the book by // adding a build step in `src/bootstrap/builder.rs`! book!( - EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook2; - EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2; - Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook1; + EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::Latest; + EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::Latest; + Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::Latest; Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1; - RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::MdBook1; + RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::Latest; RustcBook, "src/doc/rustc", "rustc", RustbookVersion::MdBook1; - RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook1; + RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::Latest; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] enum RustbookVersion { MdBook1, - MdBook2, + Latest, } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -struct Rustbook { - target: Interned, - name: Interned, - version: RustbookVersion, -} - -impl Step for Rustbook { - type Output = (); - - // rustbook is never directly called, and only serves as a shim for the nomicon and the - // reference. - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() - } - - /// Invoke `rustbook` for `target` for the doc book `name`. - /// - /// This will not actually generate any documentation if the documentation has - /// already been generated. - fn run(self, builder: &Builder<'_>) { - let src = builder.src.join("src/doc"); - builder.ensure(RustbookSrc { - target: self.target, - name: self.name, - src: INTERNER.intern_path(src), - version: self.version, - }); - } +fn doc_src(builder: &Builder<'_>) -> Interned { + INTERNER.intern_path(builder.src.join("src/doc")) } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] @@ -134,7 +108,7 @@ impl Step for UnstableBook { target: self.target, name: INTERNER.intern_str("unstable-book"), src: builder.md_doc_out(self.target), - version: RustbookVersion::MdBook1, + version: RustbookVersion::Latest, }) } } @@ -222,7 +196,7 @@ impl Step for RustbookSrc { let vers = match self.version { RustbookVersion::MdBook1 => "1", - RustbookVersion::MdBook2 => "2", + RustbookVersion::Latest => "3", }; builder.run(rustbook_cmd @@ -274,33 +248,37 @@ impl Step for TheBook { let name = self.name; // build book - builder.ensure(Rustbook { + builder.ensure(RustbookSrc { target, name: INTERNER.intern_string(name.to_string()), - version: RustbookVersion::MdBook2, + version: RustbookVersion::Latest, + src: doc_src(builder), }); // building older edition redirects let source_name = format!("{}/first-edition", name); - builder.ensure(Rustbook { + builder.ensure(RustbookSrc { target, name: INTERNER.intern_string(source_name), - version: RustbookVersion::MdBook2, + version: RustbookVersion::Latest, + src: doc_src(builder), }); let source_name = format!("{}/second-edition", name); - builder.ensure(Rustbook { + builder.ensure(RustbookSrc { target, name: INTERNER.intern_string(source_name), - version: RustbookVersion::MdBook2, + version: RustbookVersion::Latest, + src: doc_src(builder), }); let source_name = format!("{}/2018-edition", name); - builder.ensure(Rustbook { + builder.ensure(RustbookSrc { target, name: INTERNER.intern_string(source_name), - version: RustbookVersion::MdBook2, + version: RustbookVersion::Latest, + src: doc_src(builder), }); // build the version info page and CSS @@ -475,12 +453,7 @@ impl Step for Std { builder.info(&format!("Documenting stage{} std ({})", stage, target)); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(stage, builder.config.build); - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler - }; + let compiler = builder.compiler_for(stage, builder.config.build, target); builder.ensure(compile::Std { compiler, target }); let out_dir = builder.stage_out(compiler, Mode::Std) @@ -563,12 +536,7 @@ impl Step for Test { builder.info(&format!("Documenting stage{} test ({})", stage, target)); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(stage, builder.config.build); - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler - }; + let compiler = builder.compiler_for(stage, builder.config.build, target); // Build libstd docs so that we generate relative links builder.ensure(Std { stage, target }); @@ -632,12 +600,7 @@ impl Step for WhitelistedRustc { builder.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target)); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(stage, builder.config.build); - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler - }; + let compiler = builder.compiler_for(stage, builder.config.build, target); // Build libstd docs so that we generate relative links builder.ensure(Std { stage, target }); @@ -706,12 +669,7 @@ impl Step for Rustc { t!(fs::create_dir_all(&out)); // Get the correct compiler for this stage. - let compiler = builder.compiler(stage, builder.config.build); - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler - }; + let compiler = builder.compiler_for(stage, builder.config.build, target); if !builder.config.compiler_docs { builder.info("\tskipping - compiler/librustdoc docs disabled"); @@ -728,7 +686,7 @@ impl Step for Rustc { // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); - cargo.env("RUSTDOCFLAGS", "--document-private-items"); + cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden"); compile::rustc_cargo(builder, &mut cargo); // Only include compiler crates, no dependencies of those, such as `libc`. @@ -807,12 +765,7 @@ impl Step for Rustdoc { t!(fs::create_dir_all(&out)); // Get the correct compiler for this stage. - let compiler = builder.compiler(stage, builder.config.build); - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler - }; + let compiler = builder.compiler_for(stage, builder.config.build, target); if !builder.config.compiler_docs { builder.info("\tskipping - compiler/librustdoc docs disabled"); @@ -923,11 +876,6 @@ impl Step for UnstableBookGen { fn run(self, builder: &Builder<'_>) { let target = self.target; - builder.ensure(compile::Std { - compiler: builder.compiler(builder.top_stage, builder.config.build), - target, - }); - builder.info(&format!("Generating unstable book md files ({})", target)); let out = builder.md_doc_out(target).join("unstable-book"); builder.create_dir(&out); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index a1f89d6c86..179accda0c 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -44,6 +44,12 @@ pub enum Subcommand { Check { paths: Vec, }, + Clippy { + paths: Vec, + }, + Fix { + paths: Vec, + }, Doc { paths: Vec, }, @@ -52,6 +58,7 @@ pub enum Subcommand { /// Whether to automatically update stderr/stdout files bless: bool, compare_mode: Option, + pass: Option, test_args: Vec, rustc_args: Vec, fail_fast: bool, @@ -90,6 +97,8 @@ Usage: x.py [options] [...] Subcommands: build Compile either the compiler or libraries check Compile either the compiler or libraries, using cargo check + clippy Run clippy + fix Run cargo fix test Build and run some test suites bench Build and run some benchmarks doc Build documentation @@ -146,6 +155,8 @@ To learn more about a subcommand, run `./x.py -h`" let subcommand = args.iter().find(|&s| { (s == "build") || (s == "check") + || (s == "clippy") + || (s == "fix") || (s == "test") || (s == "bench") || (s == "doc") @@ -189,6 +200,12 @@ To learn more about a subcommand, run `./x.py -h`" "mode describing what file the actual ui output will be compared to", "COMPARE MODE", ); + opts.optopt( + "", + "pass", + "force {check,build,run}-pass tests to this mode.", + "check | build | run" + ); opts.optflag( "", "rustfix-coverage", @@ -281,6 +298,28 @@ Arguments: the compiler.", ); } + "clippy" => { + subcommand_help.push_str( + "\n +Arguments: + This subcommand accepts a number of paths to directories to the crates + and/or artifacts to run clippy against. For example: + + ./x.py clippy src/libcore + ./x.py clippy src/libcore src/libproc_macro", + ); + } + "fix" => { + subcommand_help.push_str( + "\n +Arguments: + This subcommand accepts a number of paths to directories to the crates + and/or artifacts to run `cargo fix` against. For example: + + ./x.py fix src/libcore + ./x.py fix src/libcore src/libproc_macro", + ); + } "test" => { subcommand_help.push_str( "\n @@ -363,10 +402,13 @@ Arguments: let cmd = match subcommand.as_str() { "build" => Subcommand::Build { paths }, "check" => Subcommand::Check { paths }, + "clippy" => Subcommand::Clippy { paths }, + "fix" => Subcommand::Fix { paths }, "test" => Subcommand::Test { paths, bless: matches.opt_present("bless"), compare_mode: matches.opt_str("compare-mode"), + pass: matches.opt_str("pass"), test_args: matches.opt_strs("test-args"), rustc_args: matches.opt_strs("rustc-args"), fail_fast: !matches.opt_present("no-fail-fast"), @@ -490,6 +532,15 @@ impl Subcommand { _ => None, } } + + pub fn pass(&self) -> Option<&str> { + match *self { + Subcommand::Test { + ref pass, .. + } => pass.as_ref().map(|s| &s[..]), + _ => None, + } + } } fn split(s: &[String]) -> Vec { diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index deda30b6bb..557586709c 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -5,12 +5,13 @@ use std::env; use std::fs; -use std::path::{Path, PathBuf, Component}; +use std::path::{Component, Path, PathBuf}; use std::process::Command; use build_helper::t; use crate::dist::{self, pkgname, sanitize_sh, tmpdir}; +use crate::Compiler; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::cache::Interned; @@ -58,7 +59,7 @@ fn install_sh( package: &str, name: &str, stage: u32, - host: Option> + host: Option>, ) { builder.info(&format!("Install {} stage{} ({:?})", package, stage, host)); @@ -144,9 +145,8 @@ macro_rules! install { $( #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $name { - pub stage: u32, + pub compiler: Compiler, pub target: Interned, - pub host: Interned, } impl $name { @@ -175,9 +175,8 @@ macro_rules! install { fn make_run(run: RunConfig<'_>) { run.builder.ensure($name { - stage: run.builder.top_stage, + compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), target: run.target, - host: run.builder.config.build, }); } @@ -190,67 +189,81 @@ macro_rules! install { install!((self, builder, _config), Docs, "src/doc", _config.docs, only_hosts: false, { - builder.ensure(dist::Docs { stage: self.stage, host: self.target }); - install_docs(builder, self.stage, self.target); + builder.ensure(dist::Docs { host: self.target }); + install_docs(builder, self.compiler.stage, self.target); }; Std, "src/libstd", true, only_hosts: true, { for target in &builder.targets { builder.ensure(dist::Std { - compiler: builder.compiler(self.stage, self.host), + compiler: self.compiler, target: *target }); - install_std(builder, self.stage, *target); + install_std(builder, self.compiler.stage, *target); } }; Cargo, "cargo", Self::should_build(_config), only_hosts: true, { - builder.ensure(dist::Cargo { stage: self.stage, target: self.target }); - install_cargo(builder, self.stage, self.target); + builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target }); + install_cargo(builder, self.compiler.stage, self.target); }; Rls, "rls", Self::should_build(_config), only_hosts: true, { - if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() || + if builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }).is_some() || Self::should_install(builder) { - install_rls(builder, self.stage, self.target); + install_rls(builder, self.compiler.stage, self.target); } else { - builder.info(&format!("skipping Install RLS stage{} ({})", self.stage, self.target)); + builder.info( + &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target), + ); } }; Clippy, "clippy", Self::should_build(_config), only_hosts: true, { - if builder.ensure(dist::Clippy { stage: self.stage, target: self.target }).is_some() || - Self::should_install(builder) { - install_clippy(builder, self.stage, self.target); + if builder.ensure(dist::Clippy { + compiler: self.compiler, + target: self.target, + }).is_some() || Self::should_install(builder) { + install_clippy(builder, self.compiler.stage, self.target); } else { - builder.info(&format!("skipping Install clippy stage{} ({})", self.stage, self.target)); + builder.info( + &format!("skipping Install clippy stage{} ({})", self.compiler.stage, self.target), + ); } }; Miri, "miri", Self::should_build(_config), only_hosts: true, { - if builder.ensure(dist::Miri { stage: self.stage, target: self.target }).is_some() || + if builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }).is_some() || Self::should_install(builder) { - install_miri(builder, self.stage, self.target); + install_miri(builder, self.compiler.stage, self.target); } else { - builder.info(&format!("skipping Install miri stage{} ({})", self.stage, self.target)); + builder.info( + &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target), + ); } }; Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, { - if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() || - Self::should_install(builder) { - install_rustfmt(builder, self.stage, self.target); + if builder.ensure(dist::Rustfmt { + compiler: self.compiler, + target: self.target + }).is_some() || Self::should_install(builder) { + install_rustfmt(builder, self.compiler.stage, self.target); } else { builder.info( - &format!("skipping Install Rustfmt stage{} ({})", self.stage, self.target)); + &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target), + ); } }; Analysis, "analysis", Self::should_build(_config), only_hosts: false, { builder.ensure(dist::Analysis { - compiler: builder.compiler(self.stage, self.host), + // Find the actual compiler (handling the full bootstrap option) which + // produced the save-analysis data because that data isn't copied + // through the sysroot uplifting. + compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target), target: self.target }); - install_analysis(builder, self.stage, self.target); + install_analysis(builder, self.compiler.stage, self.target); }; Rustc, "src/librustc", true, only_hosts: true, { builder.ensure(dist::Rustc { - compiler: builder.compiler(self.stage, self.target), + compiler: self.compiler, }); - install_rustc(builder, self.stage, self.target); + install_rustc(builder, self.compiler.stage, self.target); }; ); @@ -266,15 +279,12 @@ impl Step for Src { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let config = &run.builder.config; - let cond = config.extended && - config.tools.as_ref().map_or(true, |t| t.contains("src")); + let cond = config.extended && config.tools.as_ref().map_or(true, |t| t.contains("src")); run.path("src").default_condition(cond) } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Src { - stage: run.builder.top_stage, - }); + run.builder.ensure(Src { stage: run.builder.top_stage }); } fn run(self, builder: &Builder<'_>) { diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs index df492e0fdf..6867d62a48 100644 --- a/src/bootstrap/job.rs +++ b/src/bootstrap/job.rs @@ -32,6 +32,7 @@ use std::env; use std::io; use std::mem; +use std::ptr; use crate::Build; type HANDLE = *mut u8; @@ -118,8 +119,8 @@ pub unsafe fn setup(build: &mut Build) { SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX); // Create a new job object for us to use - let job = CreateJobObjectW(0 as *mut _, 0 as *const _); - assert!(job != 0 as *mut _, "{}", io::Error::last_os_error()); + let job = CreateJobObjectW(ptr::null_mut(), ptr::null()); + assert!(!job.is_null(), "{}", io::Error::last_os_error()); // Indicate that when all handles to the job object are gone that all // process in the object should be killed. Note that this includes our @@ -166,8 +167,8 @@ pub unsafe fn setup(build: &mut Build) { }; let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap()); - assert!(parent != 0 as *mut _, "{}", io::Error::last_os_error()); - let mut parent_handle = 0 as *mut _; + assert!(!parent.is_null(), "{}", io::Error::last_os_error()); + let mut parent_handle = ptr::null_mut(); let r = DuplicateHandle(GetCurrentProcess(), job, parent, &mut parent_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ca4489655c..4d297fa918 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -197,11 +197,11 @@ pub struct Compiler { #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum DocTests { - // Default, run normal tests and doc tests. + /// Run normal tests and doc tests (default). Yes, - // Do not run any doc tests. + /// Do not run any doc tests. No, - // Only run doc tests. + /// Only run doc tests. Only, } @@ -221,10 +221,10 @@ pub enum GitRepo { /// methods specifically on this structure itself (to make it easier to /// organize). pub struct Build { - // User-specified configuration via config.toml + /// User-specified configuration from `config.toml`. config: Config, - // Derived properties from the above two configurations + // Properties derived from the above configuration src: PathBuf, out: PathBuf, rust_info: channel::GitInfo, @@ -240,12 +240,12 @@ pub struct Build { doc_tests: DocTests, verbosity: usize, - // Targets for which to build. + // Targets for which to build build: Interned, hosts: Vec>, targets: Vec>, - // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. + // Stage 0 (downloaded) compiler and cargo or their local rust equivalents initial_rustc: PathBuf, initial_cargo: PathBuf, @@ -255,7 +255,7 @@ pub struct Build { cxx: HashMap, cc::Tool>, ar: HashMap, PathBuf>, ranlib: HashMap, PathBuf>, - // Misc + // Miscellaneous crates: HashMap, Crate>, is_sudo: bool, ci_env: CiEnv, @@ -270,14 +270,9 @@ pub struct Build { #[derive(Debug)] struct Crate { name: Interned, - version: String, deps: HashSet>, id: String, path: PathBuf, - doc_step: String, - build_step: String, - test_step: String, - bench_step: String, } impl Crate { @@ -1214,8 +1209,7 @@ impl Build { /// when this function is called. pub fn cp_r(&self, src: &Path, dst: &Path) { if self.config.dry_run { return; } - for f in t!(fs::read_dir(src)) { - let f = t!(f); + for f in self.read_dir(src) { let path = f.path(); let name = path.file_name().unwrap(); let dst = dst.join(name); diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 4a71fd2ce0..b622b3682a 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -20,7 +20,6 @@ struct Output { struct Package { id: String, name: String, - version: String, source: Option, manifest_path: String, } @@ -84,12 +83,7 @@ fn build_krate(features: &str, build: &mut Build, resolves: &mut Vec 0 { + enabled_llvm_projects.sort(); + enabled_llvm_projects.dedup(); + cfg.define("LLVM_ENABLE_PROJECTS", enabled_llvm_projects.join(";")); + } + if let Some(num_linkers) = builder.config.llvm_link_jobs { if num_linkers > 0 { cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string()); @@ -402,7 +416,7 @@ fn configure_cmake(builder: &Builder<'_>, cfg.build_arg("-j").build_arg(builder.jobs().to_string()); let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" "); - if let Some(ref s) = builder.config.llvm_cxxflags { + if let Some(ref s) = builder.config.llvm_cflags { cflags.push_str(&format!(" {}", s)); } cfg.define("CMAKE_C_FLAGS", cflags); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index be0af8be7b..1d54ca16a3 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -709,8 +709,8 @@ impl Step for Tidy { if !builder.config.vendor { cmd.arg("--no-vendor"); } - if !builder.config.verbose_tests { - cmd.arg("--quiet"); + if builder.is_verbose() { + cmd.arg("--verbose"); } let _folder = builder.fold_output(|| "tidy"); @@ -976,14 +976,10 @@ impl Step for Compiletest { } if suite == "debuginfo" { - // Skip debuginfo tests on MSVC - if builder.config.build.contains("msvc") { - return; - } - + let msvc = builder.config.build.contains("msvc"); if mode == "debuginfo" { return builder.ensure(Compiletest { - mode: "debuginfo-both", + mode: if msvc { "debuginfo-cdb" } else { "debuginfo-gdb+lldb" }, ..self }); } @@ -1069,6 +1065,11 @@ impl Step for Compiletest { } }); + if let Some(ref pass) = builder.config.cmd.pass() { + cmd.arg("--pass"); + cmd.arg(pass); + } + if let Some(ref nodejs) = builder.config.nodejs { cmd.arg("--nodejs").arg(nodejs); } @@ -1082,10 +1083,8 @@ impl Step for Compiletest { if builder.config.rust_optimize_tests { flags.push("-O".to_string()); } - if builder.config.rust_debuginfo_tests { - flags.push("-g".to_string()); - } } + flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); flags.push("-Zunstable-options".to_string()); flags.push(builder.config.cmd.rustc_args().join(" ")); @@ -1149,24 +1148,9 @@ impl Step for Compiletest { } } - if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") { - match &var.to_string_lossy().to_lowercase()[..] { - "1" | "yes" | "on" => { - assert!(builder.config.lldb_enabled, - "RUSTBUILD_FORCE_CLANG_BASED_TESTS needs Clang/LLDB to \ - be built."); - let clang_exe = builder.llvm_out(target).join("bin").join("clang"); - cmd.arg("--run-clang-based-tests-with").arg(clang_exe); - } - "0" | "no" | "off" => { - // Nothing to do. - } - other => { - // Let's make sure typos don't get unnoticed - panic!("Unrecognized option '{}' set in \ - RUSTBUILD_FORCE_CLANG_BASED_TESTS", other); - } - } + if util::forcing_clang_based_tests() { + let clang_exe = builder.llvm_out(target).join("bin").join("clang"); + cmd.arg("--run-clang-based-tests-with").arg(clang_exe); } // Get paths from cmd args @@ -1711,15 +1695,11 @@ impl Step for Crate { builder.ensure(compile::Test { compiler, target }); builder.ensure(RemoteCopyLibs { compiler, target }); - // If we're not doing a full bootstrap but we're testing a stage2 version of - // libstd, then what we're actually testing is the libstd produced in - // stage1. Reflect that here by updating the compiler that we're working - // with automatically. - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler.clone() - }; + // If we're not doing a full bootstrap but we're testing a stage2 + // version of libstd, then what we're actually testing is the libstd + // produced in stage1. Reflect that here by updating the compiler that + // we're working with automatically. + let compiler = builder.compiler_for(compiler.stage, compiler.host, target); let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand()); match mode { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index edcd68d010..bd77f7a91d 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -77,13 +77,14 @@ impl Step for ToolBuild { let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| { + let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { | "rls" | "cargo" | "clippy-driver" | "miri" + | "rustfmt" => {} _ => return, @@ -267,10 +268,6 @@ macro_rules! bootstrap_tool { } impl Tool { - pub fn get_mode(&self) -> Mode { - Mode::ToolBootstrap - } - /// Whether this tool requires LLVM to run pub fn uses_llvm_tools(&self) -> bool { match self { @@ -485,10 +482,6 @@ impl Step for Rustdoc { &[], ); - // Most tools don't get debuginfo, but rustdoc should. - cargo.env("RUSTC_DEBUGINFO", builder.config.rust_debuginfo.to_string()) - .env("RUSTC_DEBUGINFO_LINES", builder.config.rust_debuginfo_lines.to_string()); - let _folder = builder.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage)); builder.info(&format!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host)); @@ -539,9 +532,9 @@ impl Step for Cargo { } fn run(self, builder: &Builder<'_>) -> PathBuf { - // Cargo depends on procedural macros, which requires a full host - // compiler to be available, so we need to depend on that. - builder.ensure(compile::Rustc { + // Cargo depends on procedural macros, so make sure the host + // libstd/libproc_macro is available. + builder.ensure(compile::Test { compiler: self.compiler, target: builder.config.build, }); @@ -613,26 +606,26 @@ macro_rules! tool_extended { tool_extended!((self, builder), Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", {}; CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", { - // Clippy depends on procedural macros (serde), which requires a full host - // compiler to be available, so we need to depend on that. - builder.ensure(compile::Rustc { + // Clippy depends on procedural macros, so make sure that's built for + // the compiler itself. + builder.ensure(compile::Test { compiler: self.compiler, target: builder.config.build, }); }; Clippy, clippy, "src/tools/clippy", "clippy-driver", { - // Clippy depends on procedural macros (serde), which requires a full host - // compiler to be available, so we need to depend on that. - builder.ensure(compile::Rustc { + // Clippy depends on procedural macros, so make sure that's built for + // the compiler itself. + builder.ensure(compile::Test { compiler: self.compiler, target: builder.config.build, }); }; Miri, miri, "src/tools/miri", "miri", {}; CargoMiri, miri, "src/tools/miri", "cargo-miri", { - // Miri depends on procedural macros (serde), which requires a full host - // compiler to be available, so we need to depend on that. - builder.ensure(compile::Rustc { + // Miri depends on procedural macros, so make sure that's built for + // the compiler itself. + builder.ensure(compile::Test { compiler: self.compiler, target: builder.config.build, }); @@ -646,9 +639,9 @@ tool_extended!((self, builder), if clippy.is_some() { self.extra_features.push("clippy".to_owned()); } - // RLS depends on procedural macros, which requires a full host - // compiler to be available, so we need to depend on that. - builder.ensure(compile::Rustc { + // RLS depends on procedural macros, so make sure that's built for + // the compiler itself. + builder.ensure(compile::Test { compiler: self.compiler, target: builder.config.build, }); @@ -662,23 +655,14 @@ impl<'a> Builder<'a> { pub fn tool_cmd(&self, tool: Tool) -> Command { let mut cmd = Command::new(self.tool_exe(tool)); let compiler = self.compiler(0, self.config.build); - self.prepare_tool_cmd(compiler, tool, &mut cmd); - cmd - } - - /// Prepares the `cmd` provided to be able to run the `compiler` provided. - /// - /// Notably this munges the dynamic library lookup path to point to the - /// right location to run `compiler`. - fn prepare_tool_cmd(&self, compiler: Compiler, tool: Tool, cmd: &mut Command) { let host = &compiler.host; + // Prepares the `cmd` provided to be able to run the `compiler` provided. + // + // Notably this munges the dynamic library lookup path to point to the + // right location to run `compiler`. let mut lib_paths: Vec = vec![ - if compiler.stage == 0 { - self.build.rustc_snapshot_libdir() - } else { - PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)) - }, - self.cargo_out(compiler, tool.get_mode(), *host).join("deps"), + self.build.rustc_snapshot_libdir(), + self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("deps"), ]; // On MSVC a tool may invoke a C compiler (e.g., compiletest in run-make @@ -699,6 +683,7 @@ impl<'a> Builder<'a> { } } - add_lib_path(lib_paths, cmd); + add_lib_path(lib_paths, &mut cmd); + cmd } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index a162c65672..47f5edd156 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -209,7 +209,7 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> { let h = CreateFileW(path.as_ptr(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - 0 as *mut _, + ptr::null_mut(), OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, ptr::null_mut()); @@ -326,6 +326,8 @@ pub enum CiEnv { Travis, /// The AppVeyor environment, for Windows builds. AppVeyor, + /// The Azure Pipelines environment, for Linux (including Docker), Windows, and macOS builds. + AzurePipelines, } impl CiEnv { @@ -335,6 +337,8 @@ impl CiEnv { CiEnv::Travis } else if env::var("APPVEYOR").ok().map_or(false, |e| &*e == "True") { CiEnv::AppVeyor + } else if env::var("TF_BUILD").ok().map_or(false, |e| &*e == "True") { + CiEnv::AzurePipelines } else { CiEnv::None } @@ -352,3 +356,19 @@ impl CiEnv { } } } + +pub fn forcing_clang_based_tests() -> bool { + if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") { + match &var.to_string_lossy().to_lowercase()[..] { + "1" | "yes" | "on" => true, + "0" | "no" | "off" => false, + other => { + // Let's make sure typos don't go unnoticed + panic!("Unrecognized option '{}' set in \ + RUSTBUILD_FORCE_CLANG_BASED_TESTS", other) + } + } + } else { + false + } +} diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 60911d9178..8b00c1d81b 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -288,9 +288,9 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) } else { format!("static={}", link_name) }; - // The source for `compiler-rt` comes from the `compiler-builtins` crate, so - // load our env var set by cargo to find the source code. - let dir = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); + // This env var is provided by rustbuild to tell us where `compiler-rt` + // lives. + let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap(); let lib = native_lib_boilerplate( dir.as_ref(), sanitizer_name, diff --git a/src/ci/awscli-requirements.txt b/src/ci/awscli-requirements.txt new file mode 100644 index 0000000000..c1ffa525a1 --- /dev/null +++ b/src/ci/awscli-requirements.txt @@ -0,0 +1,13 @@ +awscli==1.16.201 +botocore==1.12.191 +colorama==0.3.9 +docutils==0.14 +jmespath==0.9.4 +pyasn1==0.4.5 +python-dateutil==2.8.0 +PyYAML==5.1 +rsa==3.4.2 +s3transfer==0.2.1 +six==1.12.0 +urllib3==1.25.3 +futures==3.3.0; python_version < '3.0' diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml new file mode 100644 index 0000000000..2e6c3b7a99 --- /dev/null +++ b/src/ci/azure-pipelines/auto.yml @@ -0,0 +1,350 @@ +# +# Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. +# + +pr: none +trigger: + - auto + +variables: +- group: real-prod-credentials + +jobs: +- job: Linux + timeoutInMinutes: 600 + pool: + vmImage: ubuntu-16.04 + steps: + - template: steps/run.yml + strategy: + matrix: + x86_64-gnu-llvm-6.0: + IMAGE: x86_64-gnu-llvm-6.0 + RUST_BACKTRACE: 1 + + dist-x86_64-linux: + IMAGE: dist-x86_64-linux + DEPLOY: 1 + + # "alternate" deployments, these are "nightlies" but have LLVM assertions + # turned on, they're deployed to a different location primarily for + # additional testing. + dist-x86_64-linux-alt: + IMAGE: dist-x86_64-linux + DEPLOY_ALT: 1 + + # Linux builders, remaining docker images + arm-android: + IMAGE: arm-android + + armhf-gnu: + IMAGE: armhf-gnu + + dist-various-1: + IMAGE: dist-various-1 + DEPLOY: 1 + + dist-various-2: + IMAGE: dist-various-2 + DEPLOY: 1 + + dist-aarch64-linux: + IMAGE: dist-aarch64-linux + DEPLOY: 1 + + dist-android: + IMAGE: dist-android + DEPLOY: 1 + + dist-arm-linux: + IMAGE: dist-arm-linux + DEPLOY: 1 + + dist-armhf-linux: + IMAGE: dist-armhf-linux + DEPLOY: 1 + + dist-armv7-linux: + IMAGE: dist-armv7-linux + DEPLOY: 1 + + dist-i586-gnu-i586-i686-musl: + IMAGE: dist-i586-gnu-i586-i686-musl + DEPLOY: 1 + + dist-i686-freebsd: + IMAGE: dist-i686-freebsd + DEPLOY: 1 + + dist-i686-linux: + IMAGE: dist-i686-linux + DEPLOY: 1 + + dist-mips-linux: + IMAGE: dist-mips-linux + DEPLOY: 1 + + dist-mips64-linux: + IMAGE: dist-mips64-linux + DEPLOY: 1 + + dist-mips64el-linux: + IMAGE: dist-mips64el-linux + DEPLOY: 1 + + dist-mipsel-linux: + IMAGE: dist-mipsel-linux + DEPLOY: 1 + + dist-powerpc-linux: + IMAGE: dist-powerpc-linux + DEPLOY: 1 + + dist-powerpc64-linux: + IMAGE: dist-powerpc64-linux + DEPLOY: 1 + + dist-powerpc64le-linux: + IMAGE: dist-powerpc64le-linux + DEPLOY: 1 + + dist-s390x-linux: + IMAGE: dist-s390x-linux + DEPLOY: 1 + + dist-x86_64-freebsd: + IMAGE: dist-x86_64-freebsd + DEPLOY: 1 + + dist-x86_64-musl: + IMAGE: dist-x86_64-musl + DEPLOY: 1 + + dist-x86_64-netbsd: + IMAGE: dist-x86_64-netbsd + DEPLOY: 1 + + asmjs: + IMAGE: asmjs + i686-gnu: + IMAGE: i686-gnu + i686-gnu-nopt: + IMAGE: i686-gnu-nopt + test-various: + IMAGE: test-various + x86_64-gnu: + IMAGE: x86_64-gnu + x86_64-gnu-full-bootstrap: + IMAGE: x86_64-gnu-full-bootstrap + x86_64-gnu-aux: + IMAGE: x86_64-gnu-aux + x86_64-gnu-tools: + IMAGE: x86_64-gnu-tools + x86_64-gnu-debug: + IMAGE: x86_64-gnu-debug + x86_64-gnu-nopt: + IMAGE: x86_64-gnu-nopt + x86_64-gnu-distcheck: + IMAGE: x86_64-gnu-distcheck + mingw-check: + IMAGE: mingw-check + +- job: macOS + timeoutInMinutes: 600 + pool: + vmImage: macos-10.13 + steps: + - template: steps/run.yml + strategy: + matrix: + # OSX builders running tests, these run the full test suite. + # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some + # runners that run `//ignore-debug` tests. + # + # Note that the compiler is compiled to target 10.8 here because the Xcode + # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. + x86_64-apple: + SCRIPT: ./x.py test + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + dist-x86_64-apple: + SCRIPT: ./x.py dist + RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + + dist-x86_64-apple-alt: + SCRIPT: ./x.py dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + i686-apple: + SCRIPT: ./x.py test + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + dist-i686-apple: + SCRIPT: ./x.py dist + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + + + +- job: Windows + timeoutInMinutes: 600 + pool: + vmImage: 'vs2017-win2016' + steps: + - template: steps/run.yml + strategy: + matrix: + # 32/64 bit MSVC tests + x86_64-msvc-1: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-msvc-2: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-2 + i686-msvc-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-1 + i686-msvc-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-2 + # MSVC aux tests + x86_64-msvc-aux: + MSYS_BITS: 64 + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + x86_64-msvc-cargo: + MSYS_BITS: 64 + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + VCVARS_BAT: vcvars64.bat + # MSVC tools tests + x86_64-msvc-tools: + MSYS_BITS: 64 + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri + + # 32/64-bit MinGW builds. + # + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + i686-mingw-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-1 + MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + i686-mingw-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-2 + MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + x86_64-mingw-1: + MSYS_BITS: 64 + SCRIPT: make ci-subset-1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-mingw-2: + MSYS_BITS: 64 + SCRIPT: make ci-subset-2 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + + # 32/64 bit MSVC and GNU deployment + dist-x86_64-msvc: + RUST_CONFIGURE_ARGS: > + --build=x86_64-pc-windows-msvc + --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-msvc: + RUST_CONFIGURE_ARGS: > + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-mingw: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler + SCRIPT: python x.py dist + MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-x86_64-mingw: + MSYS_BITS: 64 + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler + MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + + # "alternate" deployment, see .travis.yml for more info + dist-x86_64-msvc-alt: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + DEPLOY_ALT: 1 diff --git a/src/ci/azure-pipelines/master.yml b/src/ci/azure-pipelines/master.yml new file mode 100644 index 0000000000..9742c71965 --- /dev/null +++ b/src/ci/azure-pipelines/master.yml @@ -0,0 +1,25 @@ +# +# Azure Pipelines job to publish toolstate. Only triggers on pushes to master. +# + +pr: none +trigger: + - master + +variables: +- group: real-prod-credentials + +pool: + vmImage: ubuntu-16.04 + +steps: +- checkout: self + fetchDepth: 2 + +- script: | + export MESSAGE_FILE=$(mktemp -t msg.XXXXXX) + . src/ci/docker/x86_64-gnu-tools/repo.sh + commit_toolstate_change "$MESSAGE_FILE" "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN" + displayName: Publish toolstate + env: + TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN) diff --git a/src/ci/azure-pipelines/pr.yml b/src/ci/azure-pipelines/pr.yml new file mode 100644 index 0000000000..88b5067b4a --- /dev/null +++ b/src/ci/azure-pipelines/pr.yml @@ -0,0 +1,33 @@ +# +# Azure Pipelines pull request build for Rust +# + +trigger: none +pr: +- master + +jobs: +- job: Linux + timeoutInMinutes: 600 + pool: + vmImage: ubuntu-16.04 + steps: + - template: steps/run.yml + strategy: + matrix: + x86_64-gnu-llvm-6.0: + IMAGE: x86_64-gnu-llvm-6.0 + mingw-check: + IMAGE: mingw-check + +# TODO: enable this job if the commit message matches this regex, need tools +# figure out how to get the current commit message on azure and stick it in a +# condition somewhere +# if: commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/ +# - job: Linux-x86_64-gnu-tools +# pool: +# vmImage: ubuntu-16.04 +# steps: +# - template: steps/run.yml +# variables: +# IMAGE: x86_64-gnu-tools diff --git a/src/ci/azure-pipelines/steps/install-clang.yml b/src/ci/azure-pipelines/steps/install-clang.yml new file mode 100644 index 0000000000..0cd6f24e32 --- /dev/null +++ b/src/ci/azure-pipelines/steps/install-clang.yml @@ -0,0 +1,40 @@ +steps: + +- bash: | + set -e + curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - + + export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang + echo "##vso[task.setvariable variable=CC]$CC" + + export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ + echo "##vso[task.setvariable variable=CXX]$CXX" + + # Configure `AR` specifically so rustbuild doesn't try to infer it as + # `clang-ar` by accident. + echo "##vso[task.setvariable variable=AR]ar" + displayName: Install clang (OSX) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) + +# If we're compiling for MSVC then we, like most other distribution builders, +# switch to clang as the compiler. This'll allow us eventually to enable LTO +# amongst LLVM and rustc. Note that we only do this on MSVC as I don't think +# clang has an output mode compatible with MinGW that we need. If it does we +# should switch to clang for MinGW as well! +# +# Note that the LLVM installer is an NSIS installer +# +# Original downloaded here came from +# http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe +- script: | + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.exe" + set CLANG_DIR=%CD%\citools\clang-rust + %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR% + set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe + echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) + displayName: Install clang (Windows) + +# Note that we don't install clang on Linux since its compiler story is just so +# different. Each container has its own toolchain configured appropriately +# already. diff --git a/src/ci/azure-pipelines/steps/install-sccache.yml b/src/ci/azure-pipelines/steps/install-sccache.yml new file mode 100644 index 0000000000..427e50f571 --- /dev/null +++ b/src/ci/azure-pipelines/steps/install-sccache.yml @@ -0,0 +1,21 @@ +steps: + +- bash: | + set -e + curl -fo /usr/local/bin/sccache https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin + chmod +x /usr/local/bin/sccache + displayName: Install sccache (OSX) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) + +- script: | + md sccache + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" + echo ##vso[task.prependpath]%CD%\sccache + displayName: Install sccache (Windows) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +# Note that we don't install sccache on Linux since it's installed elsewhere +# through all the containers. +# +# FIXME: we should probably install sccache outside the containers and then +# mount it inside the containers so we can centralize all installation here. diff --git a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml new file mode 100644 index 0000000000..ed06679464 --- /dev/null +++ b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml @@ -0,0 +1,94 @@ +steps: +# We've had issues with the default drive in use running out of space during a +# build, and it looks like the `C:` drive has more space than the default `D:` +# drive. We should probably confirm this with the azure pipelines team at some +# point, but this seems to fix our "disk space full" problems. +- script: | + mkdir c:\MORE_SPACE + mklink /J build c:\MORE_SPACE + displayName: "Ensure build happens on C:/ instead of D:/" + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +- bash: git config --replace-all --global core.autocrlf false + displayName: "Disable git automatic line ending conversion (on C:/)" + +# Download and install MSYS2, needed primarily for the test suite (run-make) but +# also used by the MinGW toolchain for assembling things. +# +# FIXME: we should probe the default azure image and see if we can use the MSYS2 +# toolchain there. (if there's even one there). For now though this gets the job +# done. +- script: | + set MSYS_PATH=%CD%\citools\msys64 + choco install msys2 --params="/InstallDir:%MSYS_PATH% /NoPath" -y + set PATH=%MSYS_PATH%\usr\bin;%PATH% + pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar + IF "%MINGW_URL%"=="" ( + IF "%MSYS_BITS%"=="32" pacman -S --noconfirm --needed mingw-w64-i686-toolchain mingw-w64-i686-cmake mingw-w64-i686-gcc mingw-w64-i686-python2 + IF "%MSYS_BITS%"=="64" pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-python2 + ) + where rev + rev --help + where make + + echo ##vso[task.setvariable variable=MSYS_PATH]%MSYS_PATH% + echo ##vso[task.prependpath]%MSYS_PATH%\usr\bin + displayName: Install msys2 + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +# If we need to download a custom MinGW, do so here and set the path +# appropriately. +# +# Here we also do a pretty heinous thing which is to mangle the MinGW +# installation we just downloaded. Currently, as of this writing, we're using +# MinGW-w64 builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it +# appears to be the first version which contains a fix for #40546, builds +# randomly failing during LLVM due to ar.exe/ranlib.exe failures. +# +# Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds +# to contain a regression in gdb (#40184). As a result if we were to use the +# gdb provided (7.11.1) then we would fail all debuginfo tests. +# +# In order to fix spurious failures (pretty high priority) we use 6.3.0. To +# avoid disabling gdb tests we download an *old* version of gdb, specifically +# that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb +# with the 6.2.0 gdb to get tests passing. +# +# Note that we don't literally overwrite the gdb.exe binary because it appears +# to just use gdborig.exe, so that's the binary we deal with instead. +- script: | + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" + 7z x -y %MINGW_ARCHIVE% > nul + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" + mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe + echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) + displayName: Download custom MinGW + +# Otherwise pull in the MinGW installed on appveyor +- script: | + echo ##vso[task.prependpath]%MSYS_PATH%\mingw%MSYS_BITS%\bin + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) + displayName: Add MinGW to path + +# Make sure we use the native python interpreter instead of some msys equivalent +# one way or another. The msys interpreters seem to have weird path conversions +# baked in which break LLVM's build system one way or another, so let's use the +# native version which keeps everything as native as possible. +- script: | + copy C:\Python27amd64\python.exe C:\Python27amd64\python2.7.exe + echo ##vso[task.prependpath]C:\Python27amd64 + displayName: Prefer the "native" Python as LLVM has trouble building with MSYS sometimes + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +# Note that this is originally from the github releases patch of Ninja +- script: | + md ninja + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip" + 7z x -oninja 2017-03-15-ninja-win.zip + del 2017-03-15-ninja-win.zip + set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja + echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% + echo ##vso[task.prependpath]%CD%\ninja + displayName: Download and install ninja + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml new file mode 100644 index 0000000000..ab990575f9 --- /dev/null +++ b/src/ci/azure-pipelines/steps/run.yml @@ -0,0 +1,209 @@ +# FIXME(linux): need to configure core dumps, enable them, and then dump +# backtraces on failure from all core dumps: +# +# - bash: sudo apt install gdb +# - bash: sudo sh -c 'echo "/checkout/obj/cores/core.%p.%E" > /proc/sys/kernel/core_pattern' +# +# Check travis config for `gdb --batch` command to print all crash logs + +steps: + +# Disable automatic line ending conversion, which is enabled by default on +# Azure's Windows image. Having the conversion enabled caused regressions both +# in our test suite (it broke miri tests) and in the ecosystem, since we +# started shipping install scripts with CRLF endings instead of the old LF. +# +# Note that we do this a couple times during the build as the PATH and current +# user/directory change, e.g. when mingw is enabled. +- bash: git config --global core.autocrlf false + displayName: "Disable git automatic line ending conversion" + +- checkout: self + fetchDepth: 2 + +# Spawn a background process to collect CPU usage statistics which we'll upload +# at the end of the build. See the comments in the script here for more +# information. +- bash: python src/ci/cpu-usage-over-time.py &> cpu-usage.csv & + displayName: "Collect CPU-usage statistics in the background" + +- bash: printenv | sort + displayName: Show environment variables + +# Log the date, even on failure. Attempting to debug SSL certificate errors. +- bash: date + displayName: Print out date (before build) + +- bash: | + set -e + df -h + du . | sort -nr | head -n100 + displayName: Show disk usage + # FIXME: this hasn't been tested, but maybe it works on Windows? Should test! + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) + +- template: install-sccache.yml +- template: install-clang.yml + +# Install some dependencies needed to build LLDB/Clang, currently only needed +# during the `dist` target +- bash: | + set -e + brew update + brew install xz + brew install swig@3 + brew link --force swig@3 + displayName: Install build dependencies (OSX) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'), eq(variables['SCRIPT'],'./x.py dist')) + +# Switch to XCode 9.3 on OSX since it seems to be the last version that supports +# i686-apple-darwin. We'll eventually want to upgrade this and it will probably +# force us to drop i686-apple-darwin, but let's keep the wheels turning for now. +- bash: | + set -e + sudo xcode-select --switch /Applications/Xcode_9.3.app + displayName: Switch to Xcode 9.3 (OSX) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) + +- template: install-windows-build-deps.yml + +# Looks like docker containers have IPv6 disabled by default, so let's turn it +# on since libstd tests require it +- bash: | + set -e + sudo mkdir -p /etc/docker + echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json + sudo service docker restart + displayName: Enable IPv6 + condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) + +# Disable automatic line ending conversion (again). On Windows, when we're +# installing dependencies, something switches the git configuration directory or +# re-enables autocrlf. We've not tracked down the exact cause -- and there may +# be multiple -- but this should ensure submodules are checked out with the +# appropriate line endings. +- bash: git config --replace-all --global core.autocrlf false + displayName: "Disable git automatic line ending conversion" + +# Check out all our submodules, but more quickly than using git by using one of +# our custom scripts +- bash: | + set -e + mkdir -p $HOME/rustsrc + $BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) + displayName: Check out submodules (Unix) +- script: | + if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc + sh src/ci/init_repo.sh . /d/cache/rustsrc + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + displayName: Check out submodules (Windows) + +# See also the disable for autocrlf above, this just checks that it worked +# +# We check both in rust-lang/rust and in a submodule to make sure both are +# accurate. Submodules are checked out significantly later than the main +# repository in this script, so settings can (and do!) change between then. +# +# Linux (and maybe macOS) builders don't currently have dos2unix so just only +# run this step on Windows. +- bash: | + set -x + # print out the git configuration so we can better investigate failures in + # the following + git config --list --show-origin + dos2unix -ih Cargo.lock src/tools/rust-installer/install-template.sh + endings=$(dos2unix -ic Cargo.lock src/tools/rust-installer/install-template.sh) + # if endings has non-zero length, error out + if [ -n "$endings" ]; then exit 1 ; fi + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + displayName: Verify line endings are LF + +# Ensure the `aws` CLI is installed so we can deploy later on, cache docker +# images, etc. +- bash: | + set -e + source src/ci/shared.sh + sudo apt-get install -y python3-setuptools + retry pip3 install -r src/ci/awscli-requirements.txt --upgrade --user + echo "##vso[task.prependpath]$HOME/.local/bin" + displayName: Install awscli (Linux) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) +- script: pip install -r src/ci/awscli-requirements.txt + displayName: Install awscli (non-Linux) + condition: and(succeeded(), ne(variables['Agent.OS'], 'Linux')) + +# Configure our CI_JOB_NAME variable which log analyzers can use for the main +# step to see what's going on. +- bash: echo "##vso[task.setvariable variable=CI_JOB_NAME]$SYSTEM_JOBNAME" + displayName: Configure Job Name + +# As a quick smoke check on the otherwise very fast mingw-check linux builder +# check our own internal scripts. +- bash: | + set -e + git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git + cd rust-toolstate + python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "" + cd .. + rm -rf rust-toolstate + condition: and(succeeded(), eq(variables['IMAGE'], 'mingw-check')) + displayName: Verify the publish_toolstate script works + +- bash: | + set -e + # Remove any preexisting rustup installation since it can interfere + # with the cargotest step and its auto-detection of things like Clippy in + # the environment + rustup self uninstall -y || true + if [ "$IMAGE" = "" ]; then + src/ci/run.sh + else + src/ci/docker/run.sh $IMAGE + fi + #timeoutInMinutes: 180 + timeoutInMinutes: 600 + env: + CI: true + SRC: . + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) + TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN) + displayName: Run build + +# If we're a deploy builder, use the `aws` command to publish everything to our +# bucket. +- bash: | + set -e + source src/ci/shared.sh + if [ "$AGENT_OS" = "Linux" ]; then + rm -rf obj/build/dist/doc + upload_dir=obj/build/dist + else + rm -rf build/dist/doc + upload_dir=build/dist + fi + ls -la $upload_dir + deploy_dir=rustc-builds + if [ "$DEPLOY_ALT" == "1" ]; then + deploy_dir=rustc-builds-alt + fi + retry aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION + env: + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) + condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) + displayName: Upload artifacts + +# Upload CPU usage statistics that we've been gathering this whole time. Always +# execute this step in case we want to inspect failed builds, but don't let +# errors here ever fail the build since this is just informational. +- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$SYSTEM_JOBNAME.csv + env: + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) + condition: variables['AWS_SECRET_ACCESS_KEY'] + continueOnError: true + displayName: Upload CPU usage statistics + +# Log the date, even on failure. Attempting to debug SSL certificate errors. +- bash: date + continueOnError: true + displayName: Print out date (after build) diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml new file mode 100644 index 0000000000..6a22e57c12 --- /dev/null +++ b/src/ci/azure-pipelines/try.yml @@ -0,0 +1,78 @@ +pr: none +trigger: +- try + +variables: +- group: real-prod-credentials + +jobs: +- job: Linux + timeoutInMinutes: 600 + pool: + vmImage: ubuntu-16.04 + steps: + - template: steps/run.yml + strategy: + matrix: + dist-x86_64-linux: + IMAGE: dist-x86_64-linux + DEPLOY: 1 + + dist-x86_64-linux-alt: + IMAGE: dist-x86_64-linux + DEPLOY_ALT: 1 + +# The macOS and Windows builds here are currently disabled due to them not being +# overly necessary on `try` builds. We also don't actually have anything that +# consumes the artifacts currently. Perhaps one day we can reenable, but for now +# it helps free up capacity on Azure. +# - job: macOS +# timeoutInMinutes: 600 +# pool: +# vmImage: macos-10.13 +# steps: +# - template: steps/run.yml +# strategy: +# matrix: +# dist-x86_64-apple: +# SCRIPT: ./x.py dist +# RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc +# DEPLOY: 1 +# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 +# MACOSX_DEPLOYMENT_TARGET: 10.7 +# NO_LLVM_ASSERTIONS: 1 +# NO_DEBUG_ASSERTIONS: 1 +# DIST_REQUIRE_ALL_TOOLS: 1 +# +# dist-x86_64-apple-alt: +# SCRIPT: ./x.py dist +# RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc +# DEPLOY_ALT: 1 +# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 +# MACOSX_DEPLOYMENT_TARGET: 10.7 +# NO_LLVM_ASSERTIONS: 1 +# NO_DEBUG_ASSERTIONS: 1 +# +# - job: Windows +# timeoutInMinutes: 600 +# pool: +# vmImage: 'vs2017-win2016' +# steps: +# - template: steps/run.yml +# strategy: +# matrix: +# dist-x86_64-msvc: +# RUST_CONFIGURE_ARGS: > +# --build=x86_64-pc-windows-msvc +# --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc +# --enable-full-tools +# --enable-profiler +# SCRIPT: python x.py dist +# DIST_REQUIRE_ALL_TOOLS: 1 +# DEPLOY: 1 +# +# dist-x86_64-msvc-alt: +# MSYS_BITS: 64 +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler +# SCRIPT: python x.py dist +# DEPLOY_ALT: 1 diff --git a/src/ci/cpu-usage-over-time.py b/src/ci/cpu-usage-over-time.py new file mode 100644 index 0000000000..daf21670b3 --- /dev/null +++ b/src/ci/cpu-usage-over-time.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# ignore-tidy-linelength + +# This is a small script that we use on CI to collect CPU usage statistics of +# our builders. By seeing graphs of CPU usage over time we hope to correlate +# that with possible improvements to Rust's own build system, ideally diagnosing +# that either builders are always fully using their CPU resources or they're +# idle for long stretches of time. +# +# This script is relatively simple, but it's platform specific. Each platform +# (OSX/Windows/Linux) has a different way of calculating the current state of +# CPU at a point in time. We then compare two captured states to determine the +# percentage of time spent in one state versus another. The state capturing is +# all platform-specific but the loop at the bottom is the cross platform part +# that executes everywhere. +# +# # Viewing statistics +# +# All builders will upload their CPU statistics as CSV files to our S3 buckets. +# These URLS look like: +# +# https://$bucket.s3.amazonaws.com/rustc-builds/$commit/cpu-$builder.csv +# +# for example +# +# https://rust-lang-ci2.s3.amazonaws.com/rustc-builds/68baada19cd5340f05f0db15a3e16d6671609bcc/cpu-x86_64-apple.csv +# +# Each CSV file has two columns. The first is the timestamp of the measurement +# and the second column is the % of idle cpu time in that time slice. Ideally +# the second column is always zero. +# +# Once you've downloaded a file there's various ways to plot it and visualize +# it. For command line usage you use the `src/etc/cpu-usage-over-time-plot.sh` +# script in this repository. + +import datetime +import sys +import time + +if sys.platform == 'linux2': + class State: + def __init__(self): + with open('/proc/stat', 'r') as file: + data = file.readline().split() + if data[0] != 'cpu': + raise Exception('did not start with "cpu"') + self.user = int(data[1]) + self.nice = int(data[2]) + self.system = int(data[3]) + self.idle = int(data[4]) + self.iowait = int(data[5]) + self.irq = int(data[6]) + self.softirq = int(data[7]) + self.steal = int(data[8]) + self.guest = int(data[9]) + self.guest_nice = int(data[10]) + + def idle_since(self, prev): + user = self.user - prev.user + nice = self.nice - prev.nice + system = self.system - prev.system + idle = self.idle - prev.idle + iowait = self.iowait - prev.iowait + irq = self.irq - prev.irq + softirq = self.softirq - prev.softirq + steal = self.steal - prev.steal + guest = self.guest - prev.guest + guest_nice = self.guest_nice - prev.guest_nice + total = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice + return float(idle) / float(total) * 100 + +elif sys.platform == 'win32': + from ctypes.wintypes import DWORD + from ctypes import Structure, windll, WinError, GetLastError, byref + + class FILETIME(Structure): + _fields_ = [ + ("dwLowDateTime", DWORD), + ("dwHighDateTime", DWORD), + ] + + class State: + def __init__(self): + idle, kernel, user = FILETIME(), FILETIME(), FILETIME() + + success = windll.kernel32.GetSystemTimes( + byref(idle), + byref(kernel), + byref(user), + ) + + assert success, WinError(GetLastError())[1] + + self.idle = (idle.dwHighDateTime << 32) | idle.dwLowDateTime + self.kernel = (kernel.dwHighDateTime << 32) | kernel.dwLowDateTime + self.user = (user.dwHighDateTime << 32) | user.dwLowDateTime + + def idle_since(self, prev): + idle = self.idle - prev.idle + user = self.user - prev.user + kernel = self.kernel - prev.kernel + return float(idle) / float(user + kernel) * 100 + +elif sys.platform == 'darwin': + from ctypes import * + libc = cdll.LoadLibrary('/usr/lib/libc.dylib') + + PROESSOR_CPU_LOAD_INFO = c_int(2) + CPU_STATE_USER = 0 + CPU_STATE_SYSTEM = 1 + CPU_STATE_IDLE = 2 + CPU_STATE_NICE = 3 + c_int_p = POINTER(c_int) + + class State: + def __init__(self): + num_cpus_u = c_uint(0) + cpu_info = c_int_p() + cpu_info_cnt = c_int(0) + err = libc.host_processor_info( + libc.mach_host_self(), + PROESSOR_CPU_LOAD_INFO, + byref(num_cpus_u), + byref(cpu_info), + byref(cpu_info_cnt), + ) + assert err == 0 + self.user = 0 + self.system = 0 + self.idle = 0 + self.nice = 0 + cur = 0 + while cur < cpu_info_cnt.value: + self.user += cpu_info[cur + CPU_STATE_USER] + self.system += cpu_info[cur + CPU_STATE_SYSTEM] + self.idle += cpu_info[cur + CPU_STATE_IDLE] + self.nice += cpu_info[cur + CPU_STATE_NICE] + cur += num_cpus_u.value + + def idle_since(self, prev): + user = self.user - prev.user + system = self.system - prev.system + idle = self.idle - prev.idle + nice = self.nice - prev.nice + return float(idle) / float(user + system + idle + nice) * 100.0 + +else: + print('unknown platform', sys.platform) + sys.exit(1) + +cur_state = State(); +print("Time,Idle") +while True: + time.sleep(1); + next_state = State(); + now = datetime.datetime.utcnow().isoformat() + idle = next_state.idle_since(cur_state) + print("%s,%s" % (now, idle)) + sys.stdout.flush() + cur_state = next_state diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index e4c2097f97..235920833f 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -72,7 +72,7 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static # TODO: What is this?! # Source of the file: https://github.com/vfdev-5/qemu-rpi2-vexpress/raw/master/vexpress-v2p-ca15-tc1.dtb -RUN curl -O https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb +RUN curl -O https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index 9eaffbf83e..01d6fce341 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -37,3 +37,11 @@ ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ src/libstd \ src/liballoc \ src/libcore + +# Debug assertions in rustc are largely covered by other builders, and LLVM +# assertions cause this builder to slow down by quite a large amount and don't +# buy us a huge amount over other builders (not sure if we've ever seen an +# asmjs-specific backend assertion trip), so disable assertions for these +# tests. +ENV NO_LLVM_ASSERTIONS=1 +ENV NO_DEBUG_ASSERTIONS=1 diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index a722a41839..5ab4be328a 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -126,7 +126,6 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ - CC_armebv7r_none_eabi=arm-none-eabi-gcc \ CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \ CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ diff --git a/src/ci/docker/dist-various-1/install-mips-musl.sh b/src/ci/docker/dist-various-1/install-mips-musl.sh index 8d05a04695..60a96e3b8e 100755 --- a/src/ci/docker/dist-various-1/install-mips-musl.sh +++ b/src/ci/docker/dist-various-1/install-mips-musl.sh @@ -5,7 +5,7 @@ mkdir /usr/local/mips-linux-musl # originally from # https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/ # OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2 -URL="https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror" +URL="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror" FILE="OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2" curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mips-linux-musl --strip-components=2 diff --git a/src/ci/docker/dist-various-1/install-mipsel-musl.sh b/src/ci/docker/dist-various-1/install-mipsel-musl.sh index 2c414744bf..9ae41218ee 100755 --- a/src/ci/docker/dist-various-1/install-mipsel-musl.sh +++ b/src/ci/docker/dist-various-1/install-mipsel-musl.sh @@ -5,7 +5,7 @@ mkdir /usr/local/mipsel-linux-musl # Note that this originally came from: # https://downloads.openwrt.org/snapshots/trunk/malta/generic/ # OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 -URL="https://s3-us-west-1.amazonaws.com/rust-lang-ci2/libc" +URL="https://rust-lang-ci2.s3.amazonaws.com/libc" FILE="OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2" curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mipsel-linux-musl --strip-components=2 diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index e7d6f201b4..53523d41a5 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -73,9 +73,9 @@ ENV CARGO_TARGET_AARCH64_FUCHSIA_RUSTFLAGS \ ENV TARGETS=x86_64-fuchsia ENV TARGETS=$TARGETS,aarch64-fuchsia -ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasi +ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh index 98d6df043b..7bf8946c4f 100755 --- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh @@ -5,7 +5,7 @@ set -ex # Originally from https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz -curl https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \ +curl https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \ tar xJf - export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH diff --git a/src/ci/docker/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/dist-x86_64-linux/build-openssl.sh index 7e391e21d1..13dae61690 100755 --- a/src/ci/docker/dist-x86_64-linux/build-openssl.sh +++ b/src/ci/docker/dist-x86_64-linux/build-openssl.sh @@ -4,7 +4,7 @@ set -ex source shared.sh VERSION=1.0.2k -URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/openssl-$VERSION.tar.gz +URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/openssl-$VERSION.tar.gz curl $URL | tar xzf - diff --git a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh index b5377c64b1..2e9b9dcc23 100755 --- a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -25,7 +25,7 @@ cd netbsd mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot -URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror +URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror # Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz curl $URL/2018-03-01-netbsd-src.tgz | tar xzf - diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index 5a83bd318c..2041ba50bc 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -18,4 +18,4 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests -ENV RUST_CHECK_TARGET check +ENV SCRIPT python2.7 ../x.py test diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 98a765e1ce..e6cd794887 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -40,9 +40,12 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then docker --version >> $hash_key cksum=$(sha512sum $hash_key | \ awk '{print $1}') + s3url="s3://$SCCACHE_BUCKET/docker/$cksum" - url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" - echo "Attempting to download $s3url" + url="https://$SCCACHE_BUCKET.s3.amazonaws.com/docker/$cksum" + upload="aws s3 cp - $s3url" + + echo "Attempting to download $url" rm -f /tmp/rustci_docker_cache set +e retry curl -y 30 -Y 10 --connect-timeout 30 -f -L -C - -o /tmp/rustci_docker_cache "$url" @@ -65,17 +68,17 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then -f "$dockerfile" \ "$context" - if [ "$s3url" != "" ]; then + if [ "$upload" != "" ]; then digest=$(docker inspect rust-ci --format '{{.Id}}') echo "Built container $digest" if ! grep -q "$digest" <(echo "$loaded_images"); then - echo "Uploading finished image to $s3url" + echo "Uploading finished image to $url" set +e docker history -q rust-ci | \ grep -v missing | \ xargs docker save | \ gzip | \ - aws s3 cp - $s3url + $upload set -e else echo "Looks like docker image is the same as before, not uploading" @@ -87,8 +90,8 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then echo "$digest" >>"$info" fi elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then - if [ -n "$TRAVIS_OS_NAME" ]; then - echo Cannot run disabled images on travis! + if isCI; then + echo Cannot run disabled images on CI! exit 1 fi # retry messes with the pipe from tar to docker. Not needed on non-travis @@ -140,9 +143,13 @@ exec docker \ --env DEPLOY \ --env DEPLOY_ALT \ --env LOCAL_USER_ID=`id -u` \ + --env CI \ --env TRAVIS \ --env TRAVIS_BRANCH \ + --env TF_BUILD \ + --env BUILD_SOURCEBRANCHNAME \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ + --env TOOLSTATE_REPO \ --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \ --volume "$HOME/.cargo:/cargo" \ --volume "$HOME/rustsrc:$HOME/rustsrc" \ diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh index d3b1cded6f..47196e8939 100644 --- a/src/ci/docker/scripts/emscripten.sh +++ b/src/ci/docker/scripts/emscripten.sh @@ -18,7 +18,7 @@ exit 1 } cd / -curl -fL https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ +curl -fL https://mozilla-games.s3.amazonaws.com/emscripten/releases/emsdk-portable.tar.gz | \ tar -xz cd /emsdk-portable diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index b1ac490a87..8cef69d9c2 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -59,7 +59,7 @@ done # Originally downloaded from: # https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz -URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz +URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}" # Fix up absolute symlinks from the system image. This can be removed diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh index d5988a2567..55899fa6c3 100644 --- a/src/ci/docker/scripts/musl-toolchain.sh +++ b/src/ci/docker/scripts/musl-toolchain.sh @@ -3,7 +3,7 @@ # # Versions of the toolchain components are configurable in `musl-cross-make/Makefile` and # musl unlike GLIBC is forward compatible so upgrading it shouldn't break old distributions. -# Right now we have: Binutils 2.27, GCC 6.3.0, musl 1.1.18 +# Right now we have: Binutils 2.27, GCC 6.4.0, musl 1.1.22. set -ex hide_output() { @@ -33,7 +33,7 @@ shift # Apparently applying `-fPIC` everywhere allows them to link successfully. export CFLAGS="-fPIC $CFLAGS" -git clone https://github.com/richfelker/musl-cross-make -b v0.9.7 +git clone https://github.com/richfelker/musl-cross-make -b v0.9.8 cd musl-cross-make hide_output make -j$(nproc) TARGET=$TARGET diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index 116c16b2f3..c2cf77d56c 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -22,7 +22,7 @@ shift export CFLAGS="-fPIC $CFLAGS" -MUSL=musl-1.1.20 +MUSL=musl-1.1.22 # may have been downloaded in a previous run if [ ! -d $MUSL ]; then diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index 4c03419894..194de3c339 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -1,6 +1,6 @@ set -ex curl -fo /usr/local/bin/sccache \ - https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl + https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl chmod +x /usr/local/bin/sccache diff --git a/src/ci/docker/test-various/Dockerfile b/src/ci/docker/test-various/Dockerfile index 611a24a69b..c45b1a9a0f 100644 --- a/src/ci/docker/test-various/Dockerfile +++ b/src/ci/docker/test-various/Dockerfile @@ -15,10 +15,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ wget \ patch -# FIXME: build the `ptx-linker` instead. -RUN curl -sL https://github.com/denzp/rust-ptx-linker/releases/download/v0.9.0-alpha.2/rust-ptx-linker.linux64.tar.gz | \ - tar -xzvC /usr/bin - RUN curl -sL https://nodejs.org/dist/v9.2.0/node-v9.2.0-linux-x64.tar.xz | \ tar -xJ diff --git a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile index f16dd98099..364f45aba2 100644 --- a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile +++ b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile @@ -21,3 +21,10 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.ignore-git=false ENV SCRIPT python2.7 ../x.py test distcheck ENV DIST_SRC 1 + +# The purpose of this builder is to test that we can `./x.py test` successfully +# from a tarball, not to test LLVM/rustc's own set of assertions. These cause a +# significant hit to CI compile time (over a half hour as observed in #61185), +# so disable assertions for this builder. +ENV NO_LLVM_ASSERTIONS=1 +ENV NO_DEBUG_ASSERTIONS=1 diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile index 70390c2ac1..a157fee16c 100644 --- a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile +++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile @@ -20,3 +20,9 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-full-bootstrap ENV SCRIPT python2.7 ../x.py build + +# In general this just slows down the build and we're just a smoke test that +# a full bootstrap works in general, so there's not much need to take this +# penalty in build times. +ENV NO_LLVM_ASSERTIONS 1 +ENV NO_DEBUG_ASSERTIONS 1 diff --git a/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile index 160b23e0b0..ef97f59caf 100644 --- a/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile @@ -24,4 +24,10 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-6.0 \ --enable-llvm-link-shared -ENV RUST_CHECK_TARGET check +ENV SCRIPT python2.7 ../x.py test src/tools/tidy && python2.7 ../x.py test + +# The purpose of this container isn't to test with debug assertions and +# this is run on all PRs, so let's get speedier builds by disabling these extra +# checks. +ENV NO_DEBUG_ASSERTIONS=1 +ENV NO_LLVM_ASSERTIONS=1 diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile index b0780fdf32..d0b244c9b7 100644 --- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile @@ -19,4 +19,4 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \ --disable-optimize-tests \ --set rust.test-compare-mode -ENV RUST_CHECK_TARGET check +ENV SCRIPT python2.7 ../x.py test diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index af0198705a..978732e3c0 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -35,12 +35,17 @@ set -e cat "$TOOLSTATE_FILE" echo +# This function checks if a particular tool is *not* in status "test-pass". +check_tool_failed() { + grep -vq '"'"$1"'":"test-pass"' "$TOOLSTATE_FILE" +} + # This function checks that if a tool's submodule changed, the tool's state must improve verify_status() { echo "Verifying status of $1..." if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then echo "This PR updated '$2', verifying if status is 'test-pass'..." - if grep -vq '"'"$1"'":"test-pass"' "$TOOLSTATE_FILE"; then + if check_tool_failed "$1"; then echo echo "⚠️ We detected that this PR updated '$1', but its tests failed." echo @@ -55,14 +60,16 @@ verify_status() { fi } -# deduplicates the submodule check and the assertion that on beta some tools MUST be passing +# deduplicates the submodule check and the assertion that on beta some tools MUST be passing. +# $1 should be "submodule_changed" to only check tools that got changed by this PR, +# or "beta_required" to check all tools that have $2 set to "beta". check_dispatch() { if [ "$1" = submodule_changed ]; then # ignore $2 (branch id) verify_status $3 $4 elif [ "$2" = beta ]; then echo "Requiring test passing for $3..." - if grep -q '"'"$3"'":"\(test\|build\)-fail"' "$TOOLSTATE_FILE"; then + if check_tool_failed "$3"; then exit 4 fi fi diff --git a/src/ci/docker/x86_64-gnu-tools/repo.sh b/src/ci/docker/x86_64-gnu-tools/repo.sh index 6364bc2aab..741d4dcbd9 100644 --- a/src/ci/docker/x86_64-gnu-tools/repo.sh +++ b/src/ci/docker/x86_64-gnu-tools/repo.sh @@ -55,7 +55,7 @@ commit_toolstate_change() { git config --global credential.helper store printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \ > "$HOME/.git-credentials" - git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git + git clone --depth=1 $TOOLSTATE_REPO cd rust-toolstate FAILURE=1 diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 3dfd338157..8b63581082 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# FIXME(61301): we need to debug spurious failures with this on Windows on +# Azure, so let's print more information in the logs. +set -x + set -o errexit set -o pipefail set -o nounset diff --git a/src/ci/run.sh b/src/ci/run.sh index 3606f54720..f19bd4e7ec 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -23,7 +23,9 @@ fi ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh" -if [ "$TRAVIS" != "true" ] || [ "$TRAVIS_BRANCH" == "auto" ]; then +branch_name=$(getCIBranch) + +if [ ! isCI ] || [ "$branch_name" = "auto" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" fi @@ -44,10 +46,11 @@ fi # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # either automatically or manually. export RUST_RELEASE_CHANNEL=stable -if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then +if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level-std=1" if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" @@ -109,7 +112,7 @@ travis_time_finish # Display the CPU and memory information. This helps us know why the CI timing # is fluctuating. travis_fold start log-system-info -if [ "$TRAVIS_OS_NAME" = "osx" ]; then +if isOSX; then system_profiler SPHardwareDataType || true sysctl hw || true ncpus=$(sysctl -n hw.ncpu) @@ -134,7 +137,7 @@ else return $retval } - do_make tidy - do_make all do_make "$RUST_CHECK_TARGET" fi + +sccache --show-stats || true diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 3ba64ad412..323d53f2be 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -24,6 +24,24 @@ function retry { done } +function isCI { + [ "$CI" = "true" ] || [ "$TRAVIS" = "true" ] || [ "$TF_BUILD" = "True" ] +} + +function isOSX { + [ "$TRAVIS_OS_NAME" = "osx" ] || [ "$AGENT_OS" = "Darwin" ] +} + +function getCIBranch { + if [ "$TRAVIS" = "true" ]; then + echo "$TRAVIS_BRANCH" + elif [ "$APPVEYOR" = "True" ]; then + echo "$APPVEYOR_REPO_BRANCH" + else + echo "$BUILD_SOURCEBRANCHNAME" + fi; +} + if ! declare -F travis_fold; then if [ "${TRAVIS-false}" = 'true' ]; then # This is a trimmed down copy of diff --git a/src/doc/book/CONTRIBUTING.md b/src/doc/book/CONTRIBUTING.md index d1d1088619..95151cbee9 100644 --- a/src/doc/book/CONTRIBUTING.md +++ b/src/doc/book/CONTRIBUTING.md @@ -39,4 +39,4 @@ a new language! We're waiting on [mdbook support] for multiple languages before we merge any in, but feel free to start! [Translations]: https://github.com/rust-lang/book/issues?q=is%3Aopen+is%3Aissue+label%3ATranslations -[mdbook support]: https://github.com/azerupi/mdBook/issues/5 \ No newline at end of file +[mdbook support]: https://github.com/rust-lang-nursery/mdBook/issues/5 diff --git a/src/doc/book/README.md b/src/doc/book/README.md index 0ac1992bbc..c47820b795 100644 --- a/src/doc/book/README.md +++ b/src/doc/book/README.md @@ -22,7 +22,7 @@ releases are updated less frequently. Building the book requires [mdBook], ideally the same 0.2.x version that rust-lang/rust uses in [this file][rust-mdbook]. To get it: -[mdBook]: https://github.com/azerupi/mdBook +[mdBook]: https://github.com/rust-lang-nursery/mdBook [rust-mdbook]: https://github.com/rust-lang/rust/blob/master/src/tools/rustbook/Cargo.toml ```bash @@ -77,7 +77,7 @@ a new language! We're waiting on [mdbook support] for multiple languages before we merge any in, but feel free to start! [Translations]: https://github.com/rust-lang/book/issues?q=is%3Aopen+is%3Aissue+label%3ATranslations -[mdbook support]: https://github.com/azerupi/mdBook/issues/5 +[mdbook support]: https://github.com/rust-lang-nursery/mdBook/issues/5 ## Graphviz dot diff --git a/src/doc/book/ci/dictionary.txt b/src/doc/book/ci/dictionary.txt index 52f3b6a0db..05f61c0a22 100644 --- a/src/doc/book/ci/dictionary.txt +++ b/src/doc/book/ci/dictionary.txt @@ -519,6 +519,7 @@ variable's variant's vers versa +vert Versioning visualstudio Vlissides diff --git a/src/doc/book/nostarch/appendices-d-and-e.md b/src/doc/book/nostarch/appendices-d-and-e.md deleted file mode 100644 index e42cedc0bd..0000000000 --- a/src/doc/book/nostarch/appendices-d-and-e.md +++ /dev/null @@ -1,236 +0,0 @@ -# Appendix D - Useful Development Tools - -In this appendix, we talk about some useful development tools that the Rust -project provides. We’ll look at automatic formatting, quick ways to apply -warning fixes, a linter, and integrating with IDEs. - -## Automatic Formatting with `rustfmt` - -The `rustfmt` tool reformats your code according to the community code style. -Many collaborative projects use `rustfmt` to prevent arguments about which -style to use when writing Rust: everyone formats their code using the tool. - -To install `rustfmt`, enter the following: - -``` -$ rustup component add rustfmt -``` - -This command gives you `rustfmt` and `cargo-fmt`, similar to how Rust gives you -both `rustc` and `cargo`. To format any Cargo project, enter the following: - -``` -$ cargo fmt -``` - -Running this command reformats all the Rust code in the current crate. This -should only change the code style, not the code semantics. For more information -on `rustfmt`, see its documentation at *https://github.com/rust-lang/rustfmt/*. - -## Fix Your Code with `rustfix` - -The rustfix tool is included with Rust installations and can automatically fix -some compiler warnings. If you’ve written code in Rust, you’ve probably seen -compiler warnings. For example, consider this code: - -Filename: src/main.rs - -``` -fn do_something() {} - -fn main() { - for i in 0..100 { - do_something(); - } -} -``` - -Here, we’re calling the `do_something` function 100 times, but we never use the -variable `i` in the body of the `for` loop. Rust warns us about that: - -``` -$ cargo build - Compiling myprogram v0.1.0 (file:///projects/myprogram) -warning: unused variable: `i` - --> src/main.rs:4:9 - | -4 | for i in 1..100 { - | ^ help: consider using `_i` instead - | - = note: #[warn(unused_variables)] on by default - - Finished dev [unoptimized + debuginfo] target(s) in 0.50s -``` - -The warning suggests that we use `_i` as a name instead: the underscore -indicates that we intend for this variable to be unused. We can automatically -apply that suggestion using the `rustfix` tool by running the command `cargo -fix`: - -``` -$ cargo fix - Checking myprogram v0.1.0 (file:///projects/myprogram) - Fixing src/main.rs (1 fix) - Finished dev [unoptimized + debuginfo] target(s) in 0.59s -``` - -When we look at *src/main.rs* again, we’ll see that `cargo fix` has changed the -code: - -Filename: src/main.rs - -``` -fn do_something() {} - -fn main() { - for _i in 0..100 { - do_something(); - } -} -``` - -The `for` loop variable is now named `_i`, and the warning no longer appears. - -You can also use the `cargo fix` command to transition your code between -different Rust editions. Editions are covered in Appendix E. - -## More Lints with Clippy - -The Clippy tool is a collection of lints to analyze your code to catch common -mistakes and improve your Rust code. - -To install Clippy, enter the following: - -``` -$ rustup component add clippy -``` - -To run Clippy’s lints on any Cargo project, enter the following: - -``` -$ cargo clippy -``` - -For example, say you write a program that uses an approximation of a -mathematical constant, such as pi, as this program does: - -Filename: src/main.rs - -``` -fn main() { - let x = 3.1415; - let r = 8.0; - println!("the area of the circle is {}", x * r * r); -} -``` - -Running `cargo clippy` on this project results in this error: - -``` -error: approximate value of `f{32, 64}::consts::PI` found. Consider using it -directly - --> src/main.rs:2:13 - | -2 | let x = 3.1415; - | ^^^^^^ - | - = note: #[deny(clippy::approx_constant)] on by default - = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant -``` - -This error lets you know that Rust has this constant defined more precisely, -and that your program would be more correct if you used the constant instead. -You would then change your code to use the `PI` constant. The following code -doesn’t result in any errors or warnings from Clippy: - -Filename: src/main.rs - -``` -fn main() { - let x = std::f64::consts::PI; - let r = 8.0; - println!("the area of the circle is {}", x * r * r); -} -``` - -For more information on Clippy, see its documentation at -*https://github.com/rust-lang/rust-clippy/*. - -## IDE Integration Using the Rust Language Server - -To help IDE integration, the Rust project distributes the *Rust Language -Server* (`rls`). This tool speaks the Language Server Protocol described at -*http://langserver.org/*, which is a specification for IDEs and programming -languages to communicate with each other. Different clients can use the `rls`, -such as the Rust plug-in for Visual Studio Code available from -*https://marketplace.visualstudio.com/items?itemName=rust-lang.rust/*. - -To install the `rls`, enter the following: - -``` -$ rustup component add rls -``` - -Then install the language server support in your particular IDE; you’ll gain -abilities such as autocompletion, jump to definition, and inline errors. - -For more information on the `rls`, see its documentation at -*https://github.com/rust-lang/rls/*. - -# Appendix E - Editions - -In Chapter 1, you saw that `cargo new` adds a bit of metadata to your -*Cargo.toml* file about an edition. This appendix talks about what that means! - -The Rust language and compiler have a six-week release cycle, meaning users get -a constant stream of new features. Other programming languages release larger -changes less often; Rust releases smaller updates more frequently. After a -while, all of these tiny changes add up. But from release to release, it can be -difficult to look back and say, “Wow, between Rust 1.10 and Rust 1.31, Rust has -changed a lot!” - -Every two or three years, the Rust team produces a new Rust *edition*. Each -edition brings together the features that have landed into a clear package with -fully updated documentation and tooling. New editions ship as part of the usual -six-week release process. - -Editions serve different purposes for different people: - -* For active Rust users, a new edition brings together incremental changes into - an easy-to-understand package. -* For non-users, a new edition signals that some major advancements have - landed, which might make Rust worth another look. -* For those developing Rust, a new edition provides a rallying point for the - project as a whole. - -At the time of this writing, two Rust editions are available: Rust 2015 and -Rust 2018. This book is written using Rust 2018 edition idioms. - -The `edition` key in *Cargo.toml* indicates which edition the compiler should -use for your code. If the key doesn’t exist, Rust uses `2015` as the edition -value for backward compatibility reasons. - -Each project can opt in to an edition other than the default 2015 edition. -Editions can contain incompatible changes, such as including a new keyword that -conflicts with identifiers in code. However, unless you opt in to those -changes, your code will continue to compile even as you upgrade the Rust -compiler version you use. - -All Rust compiler versions support any edition that existed prior to that -compiler’s release, and they can link crates of any supported editions -together. Edition changes only affect the way the compiler initially parses -code. Therefore, if you’re using Rust 2015 and one of your dependencies uses -Rust 2018, your project will compile and be able to use that dependency. The -opposite situation, where your project uses Rust 2018 and a dependency uses -Rust 2015, works as well. - -To be clear: most features will be available on all editions. Developers using -any Rust edition will continue to see improvements as new stable releases are -made. However, in some cases, mainly when new keywords are added, some new -features might only be available in later editions. You will need to switch -editions if you want to take advantage of such features. - -For more details, the *Edition Guide* at -*https://doc.rust-lang.org/stable/edition-guide/* is a complete book about -editions that enumerates the differences between editions and explains how to -automatically upgrade your code to a new edition via `cargo fix`. diff --git a/src/doc/book/nostarch/appendix-a-new-section.md b/src/doc/book/nostarch/appendix-a-new-section.md deleted file mode 100644 index 082d52961f..0000000000 --- a/src/doc/book/nostarch/appendix-a-new-section.md +++ /dev/null @@ -1,57 +0,0 @@ -This is a new section to appear at the end of Appendix A, after the “Keywords -Reserved for Future Use” section. - -### Raw Identifiers - -*Raw identifiers* are the syntax that lets you use keywords where they wouldn’t -normally be allowed. You use a raw identifier by prefixing a keyword with `r#`. - -For example, `match` is a keyword. If you try to compile the following function -that uses `match` as its name: - -Filename: src/main.rs - -``` -fn match(needle: &str, haystack: &str) -> bool { - haystack.contains(needle) -} -``` - -you’ll get this error: - -``` -error: expected identifier, found keyword `match` - --> src/main.rs:4:4 - | -4 | fn match(needle: &str, haystack: &str) -> bool { - | ^^^^^ expected identifier, found keyword -``` - -The error shows that you can’t use the keyword `match` as the function -identifier. To use `match` as a function name, you need to use the raw -identifier syntax, like this: - -Filename: src/main.rs - -``` -fn r#match(needle: &str, haystack: &str) -> bool { - haystack.contains(needle) -} - -fn main() { - assert!(r#match("foo", "foobar")); -} -``` - -This code will compile without any errors. Note the `r#` prefix on the function -name in its definition as well as where the function is called in `main`. - -Raw identifiers allow you to use any word you choose as an identifier, even if -that word happens to be a reserved keyword. In addition, raw identifiers allow -you to use libraries written in a different Rust edition than your crate uses. -For example, `try` isn’t a keyword in the 2015 edition but is in the 2018 -edition. If you depend on a library that’s written using the 2015 edition and -has a `try` function, you’ll need to use the raw identifier syntax, `r#try` in -this case, to call that function from your 2018 edition code. See Appendix E -for more information on editions. - diff --git a/src/doc/book/nostarch/chapter11-using-result-in-tests.md b/src/doc/book/nostarch/chapter11-using-result-in-tests.md deleted file mode 100644 index a1d7f28e1f..0000000000 --- a/src/doc/book/nostarch/chapter11-using-result-in-tests.md +++ /dev/null @@ -1,37 +0,0 @@ -Please insert this text on page 215 between the last two paragraphs before the -“Controlling how tests are run” section. - ---- - -### Using `Result` in Tests - -So far, we’ve written tests that panic when they fail. We can also write tests -that use `Result`! Here’s the test from Listing 11-1, rewritten to use -`Result` and return an `Err` instead of panicking: - -```rust -#[cfg(test)] -mod tests { - #[test] - fn it_works() -> Result<(), String> { - if 2 + 2 == 4 { - Ok(()) - } else { - Err(String::from("two plus two does not equal four")) - } - } -} -``` - -The `it_works` function now has a return type, `Result<(), String>`. In the -body of the function, rather than calling the `assert_eq!` macro, we return -`Ok(())` when the test passes and an `Err` with a `String` inside when the test -fails. - -Writing tests so they return a `Result` enables you to use the question -mark operator in the body of tests, which can be a convenient way to write -tests that should fail if any operation within them returns an `Err` variant. - -You can’t use the `#[should_panic]` annotation on tests that use `Result`. Instead, you should return an `Err` value directly when the test should -fail. diff --git a/src/doc/book/nostarch/chapter12-error-message-updates.md b/src/doc/book/nostarch/chapter12-error-message-updates.md deleted file mode 100644 index d6e2138485..0000000000 --- a/src/doc/book/nostarch/chapter12-error-message-updates.md +++ /dev/null @@ -1,12 +0,0 @@ -Please change the error output on page 242 to this: - -``` -warning: unused `std::result::Result` that must be used - --> src/main.rs:17:5 - | -17 | run(config); - | ^^^^^^^^^^^^ - | - = note: #[warn(unused_must_use)] on by default - = note: this `Result` may be an `Err` variant, which should be handled -``` diff --git a/src/doc/book/nostarch/chapter15-code-updates.md b/src/doc/book/nostarch/chapter15-code-updates.md deleted file mode 100644 index 14227da19f..0000000000 --- a/src/doc/book/nostarch/chapter15-code-updates.md +++ /dev/null @@ -1,11 +0,0 @@ -Please replace the "if... else if... else if" block highlighted on page 326 with this code, indented the same way as the old code was: - -``` - if percentage_of_max >= 1.0 { - self.messenger.send("Error: You are over your quota!"); - } else if percentage_of_max >= 0.9 { - self.messenger.send("Urgent warning: You've used up over 90% of your quota!"); - } else if percentage_of_max >= 0.75 { - self.messenger.send("Warning: You've used up over 75% of your quota!"); - } -``` \ No newline at end of file diff --git a/src/doc/book/nostarch/chapter15-error-message-updates.md b/src/doc/book/nostarch/chapter15-error-message-updates.md deleted file mode 100644 index d9cb2fe552..0000000000 --- a/src/doc/book/nostarch/chapter15-error-message-updates.md +++ /dev/null @@ -1,12 +0,0 @@ -Please change the output on page 312 to this output: - -``` -error[E0277]: can't compare `{integer}` with `&{integer}` - --> src/main.rs:6:5 - | -6 | assert_eq!(5, y); - | ^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}` - | - = help: the trait `std::cmp::PartialEq<&{integer}>` is not implemented for - `{integer}` -``` \ No newline at end of file diff --git a/src/doc/book/nostarch/chapter18-destructuring-nested-structs-and-enums.md b/src/doc/book/nostarch/chapter18-destructuring-nested-structs-and-enums.md deleted file mode 100644 index 0ba83c4307..0000000000 --- a/src/doc/book/nostarch/chapter18-destructuring-nested-structs-and-enums.md +++ /dev/null @@ -1,54 +0,0 @@ -#### Destructuring Nested Structs and Enums - -Until now, all our examples have been matching structs or enums that were one -level deep. Matching can work on nested items too! - -For example, we can refactor the code in Listing 18-15 to support RGB and HSV -colors in the `ChangeColor` message, as shown in Listing 18-16. - -```rust -enum Color { - Rgb(i32, i32, i32), - Hsv(i32, i32, i32) -} - -enum Message { - Quit, - Move { x: i32, y: i32 }, - Write(String), - ChangeColor(Color), -} - -fn main() { - let msg = Message::ChangeColor(Color::Hsv(0, 160, 255)); - - match msg { - Message::ChangeColor(Color::Rgb(r, g, b)) => { - println!( - "Change the color to red {}, green {}, and blue {}", - r, - g, - b - ) - }, - Message::ChangeColor(Color::Hsv(h, s, v)) => { - println!( - "Change the color to hue {}, saturation {}, and value {}", - h, - s, - v - ) - } - _ => () - } -} -``` - -Listing 18-16: Matching on nested enums - -The pattern of the first arm in the `match` expression matches a -`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then -the pattern binds to the three inner `i32` values. The pattern of the second -arm also matches a `Message::ChangeColor` enum variant, but the inner enum -matches the `Color::Hsv` variant instead. We can specify these complex -conditions in one `match` expression, even though two enums are involved. diff --git a/src/doc/book/nostarch/chapter19-new-function-pointer-text.md b/src/doc/book/nostarch/chapter19-new-function-pointer-text.md deleted file mode 100644 index f154798faa..0000000000 --- a/src/doc/book/nostarch/chapter19-new-function-pointer-text.md +++ /dev/null @@ -1,31 +0,0 @@ -Please add this text at the end of the Function Pointers section, just before -the Returning Closures section starts, so at the end of page 447 and before -page 448. - ---- - -We have another useful pattern that exploits an implementation detail of tuple -structs and tuple-struct enum variants. These types use `()` as initializer -syntax, which looks like a function call. The initializers are actually -implemented as functions returning an instance that’s constructed from their -arguments. We can use these initializer functions as function pointers that -implement the closure traits, which means we can specify the initializer -functions as arguments for methods that take closures, like so: - -``` -enum Status { - Value(u32), - Stop, -} - -let list_of_statuses: Vec = - (0u32..20) - .map(Status::Value) - .collect(); -``` - -Here we create `Status::Value` instances using each `u32` value in the range -that `map` is called on by using the initializer function of `Status::Value`. -Some people prefer this style, and some people prefer to use closures. They -compile to the same code, so use whichever style is clearer to you. - diff --git a/src/doc/book/nostarch/chapter19.md b/src/doc/book/nostarch/chapter19.md deleted file mode 100644 index a226c7fc8e..0000000000 --- a/src/doc/book/nostarch/chapter19.md +++ /dev/null @@ -1,579 +0,0 @@ -This code will compile just fine. For more about trait objects, refer to the -section “Using Trait Objects that Allow for Values of Different Types” on page -XX. - -Next, let’s look at macros! - -## Macros - -We’ve used macros like `println!` throughout this book, but we haven’t fully -explored what a macro is and how it works. The term *macro* refers to a family -of features in Rust: *declarative* macros with `macro_rules!` and three kinds -of *procedural* macros: - -* Custom `#[derive]` macros that specify code added with the `derive` attribute - used on structs and enums -* Attribute-like macros that define custom attributes usable on any item -* Function-like macros that look like function calls but operate on the tokens - specified as their argument - -We’ll talk about each of these in turn, but first, let’s look at why we even -need macros when we already have functions. - -### The Difference Between Macros and Functions - -Fundamentally, macros are a way of writing code that writes other code, which -is known as *metaprogramming*. In Appendix C, we discuss the `derive` -attribute, which generates an implementation of various traits for you. We’ve -also used the `println!` and `vec!` macros throughout the book. All of these -macros *expand* to produce more code than the code you’ve written manually. - -Metaprogramming is useful for reducing the amount of code you have to write and -maintain, which is also one of the roles of functions. However, macros have -some additional powers that functions don’t. - -A function signature must declare the number and type of parameters the -function has. Macros, on the other hand, can take a variable number of -parameters: we can call `println!("hello")` with one argument or -`println!("hello {}", name)` with two arguments. Also, macros are expanded -before the compiler interprets the meaning of the code, so a macro can, for -example, implement a trait on a given type. A function can’t, because it gets -called at runtime and a trait needs to be implemented at compile time. - -The downside to implementing a macro instead of a function is that macro -definitions are more complex than function definitions because you’re writing -Rust code that writes Rust code. Due to this indirection, macro definitions are -generally more difficult to read, understand, and maintain than function -definitions. - -Another important difference between macros and functions is that you must -define macros or bring them into scope *before* you call them in a file, as -opposed to functions you can define anywhere and call anywhere. - -### Declarative Macros with `macro_rules!` for General Metaprogramming - -The most widely used form of macros in Rust is *declarative macros*. These are -also sometimes referred to as “macros by example,” “`macro_rules!` macros,” or -just plain “macros.” At their core, declarative macros allow you to write -something similar to a Rust `match` expression. As discussed in Chapter 6, -`match` expressions are control structures that take an expression, compare the -resulting value of the expression to patterns, and then run the code associated -with the matching pattern. Macros also compare a value to patterns that are -associated with particular code: in this situation, the value is the literal -Rust source code passed to the macro; the patterns are compared with the -structure of that source code; and the code associated with each pattern, when -matched, replaces the code passed to the macro. This all happens during -compilation. - -To define a macro, you use the `macro_rules!` construct. Let’s explore how to -use `macro_rules!` by looking at how the `vec!` macro is defined. Chapter 8 -covered how we can use the `vec!` macro to create a new vector with particular -values. For example, the following macro creates a new vector containing three -integers: - -``` -let v: Vec = vec![1, 2, 3]; -``` - -We could also use the `vec!` macro to make a vector of two integers or a vector -of five string slices. We wouldn’t be able to use a function to do the same -because we wouldn’t know the number or type of values up front. - -Listing 19-36 shows a slightly simplified definition of the `vec!` macro. - -Filename: src/lib.rs - -``` -#[macro_export] -macro_rules! vec { - ( $( $x:expr ),* ) => { - { - let mut temp_vec = Vec::new(); - $( - temp_vec.push($x); - )* - temp_vec - } - }; -} -``` - -Listing 19-36: A simplified version of the `vec!` macro definition - -> Note: The actual definition of the `vec!` macro in the standard library -> includes code to preallocate the correct amount of memory up front. That code -> is an optimization that we don’t include here to make the example simpler. - -The `#[macro_export]` annotation indicates that this macro should be made -available whenever the crate in which the macro is defined is brought into -scope. Without this annotation, the macro can’t be brought into scope. - -We then start the macro definition with `macro_rules!` and the name of the -macro we’re defining *without* the exclamation mark. The name, in this case -`vec`, is followed by curly brackets denoting the body of the macro definition. - -The structure in the `vec!` body is similar to the structure of a `match` -expression. Here we have one arm with the pattern `( $( $x:expr ),* )`, -followed by `=>` and the block of code associated with this pattern. If the -pattern matches, the associated block of code will be emitted. Given that this -is the only pattern in this macro, there is only one valid way to match; any -other pattern will result in an error. More complex macros will have more than -one arm. - -Valid pattern syntax in macro definitions is different than the pattern syntax -covered in Chapter 18 because macro patterns are matched against Rust code -structure rather than values. Let’s walk through what the pattern pieces in -Listing 19-36 mean; for the full macro pattern syntax, see the reference at -*https://doc.rust-lang.org/stable/reference/macros.html*. - -First, a set of parentheses encompasses the whole pattern. A dollar sign (`$`) -is next, followed by a set of parentheses that captures values that match the -pattern within the parentheses for use in the replacement code. Within `$()` is -`$x:expr`, which matches any Rust expression and gives the expression the name -`$x`. - -The comma following `$()` indicates that a literal comma separator character -could optionally appear after the code that matches the code in `$()`. The `*` -specifies that the pattern matches zero or more of whatever precedes the `*`. - -When we call this macro with `vec![1, 2, 3];`, the `$x` pattern matches three -times with the three expressions `1`, `2`, and `3`. - -Now let’s look at the pattern in the body of the code associated with this arm: -`temp_vec.push()` within `$()*` is generated for each part that matches `$()` -in the pattern zero or more times depending on how many times the pattern -matches. The `$x` is replaced with each expression matched. When we call this -macro with `vec![1, 2, 3];`, the code generated that replaces this macro call -will be the following: - -``` -let mut temp_vec = Vec::new(); -temp_vec.push(1); -temp_vec.push(2); -temp_vec.push(3); -temp_vec -``` - -We’ve defined a macro that can take any number of arguments of any type and can -generate code to create a vector containing the specified elements. - -There are some strange edge cases with `macro_rules!`. In the future, Rust will -have a second kind of declarative macro that will work in a similar fashion but -fix some of these edge cases. After that update, `macro_rules!` will be -effectively deprecated. With this in mind, as well as the fact that most Rust -programmers will *use* macros more than *write* macros, we won’t discuss -`macro_rules!` any further. To learn more about how to write macros, consult -the online documentation or other resources, such as “The Little Book of Rust -Macros” at *https://danielkeep.github.io/tlborm/book/index.html*. - -### Procedural Macros for Generating Code from Attributes - -The second form of macros is *procedural macros*, which act more like functions -(and are a type of procedure). Procedural macros accept some code as an input, -operate on that code, and produce some code as an output rather than matching -against patterns and replacing the code with other code as declarative macros -do. - -The three kinds of procedural macros: custom derive, attribute-like, and -function-like, all work in a similar fashion. - -When creating procedural macros, the definitions must reside in their own crate -with a special crate type. This is for complex technical reasons that we hope -to eliminate in the future. Using procedural macros looks like the code in -Listing 19-37, where `some_attribute` is a placeholder for using a specific -macro. - -Filename: src/lib.rs - -``` -use proc_macro; - -#[some_attribute] -pub fn some_name(input: TokenStream) -> TokenStream { -} -``` - -Listing 19-37: An example of using a procedural macro - -The function that defines a procedural macro takes a `TokenStream` as an input -and produces a `TokenStream` as an output. The `TokenStream` type is defined by -the `proc_macro` crate that is included with Rust and represents a sequence of -tokens. This is the core of the macro: the source code that the macro is -operating on makes up the input `TokenStream`, and the code the macro produces -is the output `TokenStream`. The function also has an attribute attached to it -that specifies which kind of procedural macro we’re creating. We can have -multiple kinds of procedural macros in the same crate. - -Let’s look at the different kinds of procedural macros. We’ll start with a -custom derive macro and then explain the small dissimilarities that make the -other forms different. - -### How to Write a Custom `derive` Macro - -Let’s create a crate named `hello_macro` that defines a trait named -`HelloMacro` with one associated function named `hello_macro`. Rather than -making our crate users implement the `HelloMacro` trait for each of their -types, we’ll provide a procedural macro so users can annotate their type with -`#[derive(HelloMacro)]` to get a default implementation of the `hello_macro` -function. The default implementation will print `Hello, Macro! My name is -TypeName!` where `TypeName` is the name of the type on which this trait has -been defined. In other words, we’ll write a crate that enables another -programmer to write code like Listing 19-38 using our crate. - -Filename: src/main.rs - -``` -use hello_macro::HelloMacro; -use hello_macro_derive::HelloMacro; - -#[derive(HelloMacro)] -struct Pancakes; - -fn main() { - Pancakes::hello_macro(); -} -``` - -Listing 19-38: The code a user of our crate will be able to write when using -our procedural macro - -This code will print `Hello, Macro! My name is Pancakes!` when we’re done. The -first step is to make a new library crate, like this: - -``` -$ cargo new hello_macro --lib -``` - -Next, we’ll define the `HelloMacro` trait and its associated function: - -Filename: src/lib.rs - -``` -pub trait HelloMacro { - fn hello_macro(); -} -``` - -We have a trait and its function. At this point, our crate user could implement -the trait to achieve the desired functionality, like so: - -``` -use hello_macro::HelloMacro; - -struct Pancakes; - -impl HelloMacro for Pancakes { - fn hello_macro() { - println!("Hello, Macro! My name is Pancakes!"); - } -} - -fn main() { - Pancakes::hello_macro(); -} -``` - -However, they would need to write the implementation block for each type they -wanted to use with `hello_macro`; we want to spare them from having to do this -work. - -Additionally, we can’t yet provide the `hello_macro` function with default -implementation that will print the name of the type the trait is implemented -on: Rust doesn’t have reflection capabilities, so it can’t look up the type’s -name at runtime. We need a macro to generate code at compile time. - -The next step is to define the procedural macro. At the time of this writing, -procedural macros need to be in their own crate. Eventually, this restriction -might be lifted. The convention for structuring crates and macro crates is as -follows: for a crate named `foo`, a custom derive procedural macro crate is -called `foo_derive`. Let’s start a new crate called `hello_macro_derive` inside -our `hello_macro` project: - -``` -$ cargo new hello_macro_derive --lib -``` - -Our two crates are tightly related, so we create the procedural macro crate -within the directory of our `hello_macro` crate. If we change the trait -definition in `hello_macro`, we’ll have to change the implementation of the -procedural macro in `hello_macro_derive` as well. The two crates will need to -be published separately, and programmers using these crates will need to add -both as dependencies and bring them both into scope. We could instead have the -`hello_macro` crate use `hello_macro_derive` as a dependency and reexport the -procedural macro code. However, the way we’ve structured the project makes it -possible for programmers to use `hello_macro` even if they don’t want the -`derive` functionality. - -We need to declare the `hello_macro_derive` crate as a procedural macro crate. -We’ll also need functionality from the `syn` and `quote` crates, as you’ll see -in a moment, so we need to add them as dependencies. Add the following to the -*Cargo.toml* file for `hello_macro_derive`: - -Filename: hello_macro_derive/Cargo.toml - -``` -[lib] -proc-macro = true - -[dependencies] -syn = "0.14.4" -quote = "0.6.3" -``` - -To start defining the procedural macro, place the code in Listing 19-39 into -your *src/lib.rs* file for the `hello_macro_derive` crate. Note that this code -won’t compile until we add a definition for the `impl_hello_macro` function. - -Filename: hello_macro_derive/src/lib.rs - -``` -extern crate proc_macro; - -use crate::proc_macro::TokenStream; -use quote::quote; -use syn; - -#[proc_macro_derive(HelloMacro)] -pub fn hello_macro_derive(input: TokenStream) -> TokenStream { - // Construct a representation of Rust code as a syntax tree - // that we can manipulate - let ast = syn::parse(input).unwrap(); - - // Build the trait implementation - impl_hello_macro(&ast) -} -``` - -Listing 19-39: Code that most procedural macro crates will require in order to -process Rust code - -Notice that we’ve split the code into the `hello_macro_derive` function -responsible for parsing the `TokenStream` and the `impl_hello_macro` function -responsible for transforming the syntax tree: this makes writing a procedural -macro more convenient. The code in the outer function (`hello_macro_derive` in -this case) will be the same for almost every procedural macro crate you see or -create. The code you specify in the body of the inner function -(`impl_hello_macro` in this case) will be different depending on your -procedural macro’s purpose. - -We’ve introduced three new crates: `proc_macro`, `syn` (available from -*https://crates.io/crates/syn*), and `quote` (available from -*https://crates.io/crates/quote*). The `proc_macro` crate comes with Rust, so -we didn’t need to add that to the dependencies in *Cargo.toml*. The -`proc_macro` crate is the compiler’s API that allows us to read and manipulate -Rust code from our code. - -The `syn` crate parses Rust code from a string into a data structure that we -can perform operations on. The `quote` crate turns `syn` data structures back -into Rust code. These crates make it much simpler to parse any sort of Rust -code we might want to handle: writing a full parser for Rust code is no simple -task. - -The `hello_macro_derive` function will be called when a user of our library -specifies `#[derive(HelloMacro)]` on a type. This is possible because we’ve -annotated the `hello_macro_derive` function here with `proc_macro_derive` and -specified the name, `HelloMacro`, which matches our trait name; this is the -convention most procedural macros follow. - -The `hello_macro_derive` function first converts the `input` from a -`TokenStream` to a data structure that we can then interpret and perform -operations on. This is where `syn` comes into play. The `parse` function in -`syn` takes a `TokenStream` and returns a `DeriveInput` struct representing the -parsed Rust code. Listing 19-40 shows the relevant parts of the `DeriveInput` -struct we get from parsing the `struct Pancakes;` string: - -``` -DeriveInput { - // --snip-- - - ident: Ident { - ident: "Pancakes", - span: #0 bytes(95..103) - }, - data: Struct( - DataStruct { - struct_token: Struct, - fields: Unit, - semi_token: Some( - Semi - ) - } - ) -} -``` - -Listing 19-40: The `DeriveInput` instance we get when parsing the code that has -the macro’s attribute in Listing 19-38 - -The fields of this struct show that the Rust code we’ve parsed is a unit struct -with the `ident` (identifier, meaning the name) of `Pancakes`. There are more -fields on this struct for describing all sorts of Rust code; check the `syn` -documentation for `DeriveInput` at -*https://docs.rs/syn/0.14.4/syn/struct.DeriveInput.html* for more information. - -Soon we’ll define the `impl_hello_macro` function, which is where we’ll build -the new Rust code we want to include. But before we do, note that the output -for our derive macro is also a `TokenStream`. The returned `TokenStream` is -added to the code that our crate users write, so when they compile their crate, -they’ll get the extra functionality that we provide in the modified -`TokenStream`. - -You might have noticed that we’re calling `unwrap` to cause the -`hello_macro_derive` function to panic if the call to the `syn::parse` function -fails here. It’s necessary for our procedural macro to panic on errors because -`proc_macro_derive` functions must return `TokenStream` rather than `Result` to -conform to the procedural macro API. We’ve simplified this example by using -`unwrap`; in production code, you should provide more specific error messages -about what went wrong by using `panic!` or `expect`. - -Now that we have the code to turn the annotated Rust code from a `TokenStream` -into a `DeriveInput` instance, let’s generate the code that implements the -`HelloMacro` trait on the annotated type, as shown in Listing 19-41. - -Filename: hello_macro_derive/src/lib.rs - -``` -fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { - let name = &ast.ident; - let gen = quote! { - impl HelloMacro for #name { - fn hello_macro() { - println!("Hello, Macro! My name is {}", stringify!(#name)); - } - } - }; - gen.into() -} -``` - -Listing 19-41: Implementing the `HelloMacro` trait using the parsed Rust code - -We get an `Ident` struct instance containing the name (identifier) of the -annotated type using `ast.ident`. The struct in Listing 19-40 shows that when -we run the `impl_hello_macro` function on the code in Listing 19-38, the -`ident` we get will have the `ident` field with a value of `"Pancakes"`. Thus, -the `name` variable in Listing 19-41 will contain an `Ident` struct instance -that, when printed, will be the string `"Pancakes"`, the name of the struct in -Listing 19-38. - -The `quote!` macro lets us define the Rust code that we want to return. The -compiler expects something different to the direct result of the `quote!` -macro’s execution, so we need to convert it to a `TokenStream`. We do this by -calling the `into` method, which consumes this intermediate representation and -returns a value of the required `TokenStream` type. - -The `quote!` macro also provides some very cool templating mechanics: we can -enter `#name`, and `quote!` will replace it with the value in the variable -`name`. You can even do some repetition similar to the way regular macros work. -Check out the `quote` crate’s docs at *https://docs.rs/quote* for a thorough -introduction. - -We want our procedural macro to generate an implementation of our `HelloMacro` -trait for the type the user annotated, which we can get by using `#name`. The -trait implementation has one function, `hello_macro`, whose body contains the -functionality we want to provide: printing `Hello, Macro! My name is` and then -the name of the annotated type. - -The `stringify!` macro used here is built into Rust. It takes a Rust -expression, such as `1 + 2`, and at compile time turns the expression into a -string literal, such as `"1 + 2"`. This is different than `format!` or -`println!`, macros which evaluate the expression and then turn the result into -a `String`. There is a possibility that the `#name` input might be an -expression to print literally, so we use `stringify!`. Using `stringify!` also -saves an allocation by converting `#name` to a string literal at compile time. - -At this point, `cargo build` should complete successfully in both `hello_macro` -and `hello_macro_derive`. Let’s hook up these crates to the code in Listing -19-38 to see the procedural macro in action! Create a new binary project in -your *projects* directory using `cargo new pancakes`. We need to add -`hello_macro` and `hello_macro_derive` as dependencies in the `pancakes` -crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` and -`hello_macro_derive` to *https://crates.io/*, they would be regular -dependencies; if not, you can specify them as `path` dependencies as follows: - -``` -[dependencies] -hello_macro = { path = "../hello_macro" } -hello_macro_derive = { path = "../hello_macro/hello_macro_derive" } -``` - -Put the code in Listing 19-38 into *src/main.rs*, and run `cargo run`: it -should print `Hello, Macro! My name is Pancakes!` The implementation of the -`HelloMacro` trait from the procedural macro was included without the -`pancakes` crate needing to implement it; the `#[derive(HelloMacro)]` added the -trait implementation. - -Next, let’s explore how the other kinds of procedural macros differ from custom -derive macros. - -### Attribute-like macros - -Attribute-like macros are similar to custom derive macros, but instead of -generating code for the `derive` attribute, they allow you to create new -attributes. They’re also more flexible: `derive` only works for structs and -enums; attributes can be applied to other items as well, such as functions. -Here’s an example of using an attribute-like macro: say you have an attribute -named `route` that annotates functions when using a web application framework: - -``` -#[route(GET, "/")] -fn index() { -``` - -This `#[route]` attribute would be defined by the framework as a procedural -macro. The signature of the macro definition function would look like this: - -``` -#[proc_macro_attribute] -pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream { -``` - -Here, we have two parameters of type `TokenStream`. The first is for the -contents of the attribute: the `GET, "/"` part. The second is the body of the -item the attribute is attached to: in this case, `fn index() {}` and the rest -of the function’s body. - -Other than that, attribute-like macros work the same way as custom derive -macros: you create a crate with the `proc-macro` crate type and implement a -function that generates the code you want! - -### Function-like macros - -Function-like macros define macros that look like function calls. Similarly to -`macro_rules!` macros, they’re more flexible than functions in that they can -take an unknown number of arguments, for example. However, `macro_rules!` -macros can only be defined using the match-like syntax we discussed in the -section “Declarative Macros with `macro_rules!` for General Metaprogramming” on -page XX. Function-like macros take a `TokenStream` parameter and their -definition manipulates that `TokenStream` using Rust code as the other two -types of procedural macros do. An example of a function-like macro is an `sql!` -macro that might be called like so: - -``` -let sql = sql!(SELECT * FROM posts WHERE id=1); -``` - -This macro would parse the SQL statement inside it and check that it’s -syntactically correct, which is much more complex processing than a -`macro_rules!` macro can do. The `sql!` macro would be defined like this: - -``` -#[proc_macro] -pub fn sql(input: TokenStream) -> TokenStream { -``` - -This definition is similar to the custom derive macro’s signature: we receive -the tokens that are inside the parentheses and return the code we wanted to -generate. - -## Summary - -Whew! Now you have some Rust features in your toolbox that you won’t use often, -but you’ll know they’re available in particular circumstances. We’ve introduced -several complex topics, so when you encounter them in error message suggestions -or in other peoples’ code, you’ll recognize these concepts and syntax. Use this -chapter as a reference to guide you to solutions. - -Next, we’ll put everything we’ve discussed throughout the book into practice -and do one more project! - diff --git a/src/doc/book/src/appendix-02-operators.md b/src/doc/book/src/appendix-02-operators.md index 41077ba1b5..3bddf322df 100644 --- a/src/doc/book/src/appendix-02-operators.md +++ b/src/doc/book/src/appendix-02-operators.md @@ -36,7 +36,7 @@ overload that operator is listed. | `-` | `- expr` | Arithmetic negation | `Neg` | | `-` | `expr - expr` | Arithmetic subtraction | `Sub` | | `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubAssign` | -| `->` | `fn(...) -> type`, \|...\| -> type | Function and closure return type | | +| `->` | `fn(...) -> type`, |...| -> type | Function and closure return type | | | `.` | `expr.ident` | Member access | | | `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal | | | `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | | @@ -64,10 +64,10 @@ overload that operator is listed. | `@` | `ident @ pat` | Pattern binding | | | `^` | `expr ^ expr` | Bitwise exclusive OR | `BitXor` | | `^=` | `var ^= expr` | Bitwise exclusive OR and assignment | `BitXorAssign` | -| \| | pat \| pat | Pattern alternatives | | -| \| | expr \| expr | Bitwise OR | `BitOr` | -| \|= | var \|= expr | Bitwise OR and assignment | `BitOrAssign` | -| \|\| | expr \|\| expr | Logical OR | | +| | | pat | pat | Pattern alternatives | | +| | | expr | expr | Bitwise OR | `BitOr` | +| |= | var |= expr | Bitwise OR and assignment | `BitOrAssign` | +| || | expr || expr | Logical OR | | | `?` | `expr?` | Error propagation | | ### Non-operator Symbols @@ -90,7 +90,7 @@ locations. | `br"..."`, `br#"..."#`, `br##"..."##`, etc. | Raw byte string literal, combination of raw and byte string literal | | `'...'` | Character literal | | `b'...'` | ASCII byte literal | -| \|...\| expr | Closure | +| |...| expr | Closure | | `!` | Always empty bottom type for diverging functions | | `_` | “Ignored” pattern binding; also used to make integer literals readable | diff --git a/src/doc/book/src/appendix-03-derivable-traits.md b/src/doc/book/src/appendix-03-derivable-traits.md index 876d4cd8a5..eb49b304d7 100644 --- a/src/doc/book/src/appendix-03-derivable-traits.md +++ b/src/doc/book/src/appendix-03-derivable-traits.md @@ -125,9 +125,9 @@ returned from `to_vec` will need to own its instances, so `to_vec` calls `clone` on each item. Thus, the type stored in the slice must implement `Clone`. The `Copy` trait allows you to duplicate a value by only copying bits stored on -the stack; no arbitrary code is necessary. See the [“Stack-Only Data: Copy”] -[stack-only-data-copy] section in Chapter 4 for more information -on `Copy`. +the stack; no arbitrary code is necessary. See the [“Stack-Only Data: +Copy”][stack-only-data-copy] section in Chapter 4 for more +information on `Copy`. The `Copy` trait doesn’t define any methods to prevent programmers from overloading those methods and violating the assumption that no arbitrary code @@ -167,9 +167,9 @@ derive `Default`. The `Default::default` function is commonly used in combination with the struct update syntax discussed in the [“Creating Instances From Other Instances With -Struct Update Syntax”] -[creating-instances-from-other-instances-with-struct-update-syntax] section in Chapter 5. You can customize a few fields of a struct and then +Struct Update +Syntax”][creating-instances-from-other-instances-with-struct-update-syntax] +section in Chapter 5. You can customize a few fields of a struct and then set and use a default value for the rest of the fields by using `..Default::default()`. diff --git a/src/doc/book/src/appendix-04-useful-development-tools.md b/src/doc/book/src/appendix-04-useful-development-tools.md index c84bfcd11a..ec40d1cbef 100644 --- a/src/doc/book/src/appendix-04-useful-development-tools.md +++ b/src/doc/book/src/appendix-04-useful-development-tools.md @@ -98,8 +98,8 @@ different Rust editions. Editions are covered in Appendix E. ## More Lints with Clippy -The Clippy tool is a collection of lints to analyze your code to catch common -mistakes and improve your Rust code. +The Clippy tool is a collection of lints to analyze your code so you can catch +common mistakes and improve your Rust code. To install Clippy, enter the following: @@ -139,9 +139,9 @@ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it dir = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant ``` -This error lets you know that Rust has this constant defined more precisely, -and that your program would be more correct if you used the constant instead. -You would then change your code to use the `PI` constant. The following code +This error lets you know that Rust has this constant defined more precisely and +that your program would be more correct if you used the constant instead. You +would then change your code to use the `PI` constant. The following code doesn’t result in any errors or warnings from Clippy: Filename: src/main.rs diff --git a/src/doc/book/src/appendix-05-editions.md b/src/doc/book/src/appendix-05-editions.md index 5f95b82584..ac75c4181d 100644 --- a/src/doc/book/src/appendix-05-editions.md +++ b/src/doc/book/src/appendix-05-editions.md @@ -1,4 +1,5 @@ # Appendix E - Editions + In Chapter 1, you saw that `cargo new` adds a bit of metadata to your *Cargo.toml* file about an edition. This appendix talks about what that means! diff --git a/src/doc/book/src/appendix-06-translation.md b/src/doc/book/src/appendix-06-translation.md index dee8e6f221..937928bf44 100644 --- a/src/doc/book/src/appendix-06-translation.md +++ b/src/doc/book/src/appendix-06-translation.md @@ -21,3 +21,4 @@ For resources in languages other than English. Most are still in progress; see - [Tagalog](https://github.com/josephace135/book) - [Esperanto](https://github.com/psychoslave/Rust-libro) - [ελληνική](https://github.com/TChatzigiannakis/rust-book-greek) +- [Svenska](https://github.com/sebras/book) diff --git a/src/doc/book/src/ch01-03-hello-cargo.md b/src/doc/book/src/ch01-03-hello-cargo.md index 37ca76e490..34428e5f94 100644 --- a/src/doc/book/src/ch01-03-hello-cargo.md +++ b/src/doc/book/src/ch01-03-hello-cargo.md @@ -13,10 +13,10 @@ using Cargo, adding dependencies will be much easier to do. Because the vast majority of Rust projects use Cargo, the rest of this book assumes that you’re using Cargo too. Cargo comes installed with Rust if you -used the official installers discussed in the [“Installation”] -[installation] section. If you installed Rust through some other -means, check whether Cargo is installed by entering the following into your -terminal: +used the official installers discussed in the +[“Installation”][installation] section. If you installed Rust +through some other means, check whether Cargo is installed by entering the +following into your terminal: ```text $ cargo --version diff --git a/src/doc/book/src/ch02-00-guessing-game-tutorial.md b/src/doc/book/src/ch02-00-guessing-game-tutorial.md index 7ac6d3da83..e30316fd58 100644 --- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md +++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md @@ -157,10 +157,10 @@ let foo = bar; This line creates a new variable named `foo` and binds it to the value of the `bar` variable. In Rust, variables are immutable by default. We’ll be -discussing this concept in detail in the [“Variables and Mutability”] -[variables-and-mutability] section in Chapter 3. The following -example shows how to use `mut` before the variable name to make a variable -mutable: +discussing this concept in detail in the [“Variables and +Mutability”][variables-and-mutability] section in Chapter 3. +The following example shows how to use `mut` before the variable name to make +a variable mutable: ```rust,ignore let foo = 5; // immutable @@ -418,7 +418,7 @@ everything from the *registry*, which is a copy of data from [Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem post their open source Rust projects for others to use. -[cratesio]: https://crates.io +[cratesio]: https://crates.io/ After updating the registry, Cargo checks the `[dependencies]` section and downloads any crates you don’t have yet. In this case, although we only listed diff --git a/src/doc/book/src/ch03-02-data-types.md b/src/doc/book/src/ch03-02-data-types.md index 02fcf5d66b..228e4316b2 100644 --- a/src/doc/book/src/ch03-02-data-types.md +++ b/src/doc/book/src/ch03-02-data-types.md @@ -8,9 +8,9 @@ Keep in mind that Rust is a *statically typed* language, which means that it must know the types of all variables at compile time. The compiler can usually infer what type we want to use based on the value and how we use it. In cases when many types are possible, such as when we converted a `String` to a numeric -type using `parse` in the [“Comparing the Guess to the Secret Number”] -[comparing-the-guess-to-the-secret-number] section in Chapter 2, -we must add a type annotation, like this: +type using `parse` in the [“Comparing the Guess to the Secret +Number”][comparing-the-guess-to-the-secret-number] section in +Chapter 2, we must add a type annotation, like this: ```rust let guess: u32 = "42".parse().expect("Not a number!"); @@ -107,7 +107,8 @@ which you’d use `isize` or `usize` is when indexing some sort of collection. > checks for integer overflow that cause your program to *panic* at runtime if > this behavior occurs. Rust uses the term panicking when a program exits with > an error; we’ll discuss panics in more depth in the [“Unrecoverable Errors -> with `panic!`”][unrecoverable-errors-with-panic] section in Chapter 9. +> with `panic!`”][unrecoverable-errors-with-panic] section in +> Chapter 9. > > When you’re compiling in release mode with the `--release` flag, Rust does > *not* include checks for integer overflow that cause panics. Instead, if diff --git a/src/doc/book/src/ch03-05-control-flow.md b/src/doc/book/src/ch03-05-control-flow.md index 6d3b46c944..52ce3d5a9f 100644 --- a/src/doc/book/src/ch03-05-control-flow.md +++ b/src/doc/book/src/ch03-05-control-flow.md @@ -35,8 +35,9 @@ condition. In this case, the condition checks whether or not the variable condition is true is placed immediately after the condition inside curly brackets. Blocks of code associated with the conditions in `if` expressions are sometimes called *arms*, just like the arms in `match` expressions that we -discussed in the [“Comparing the Guess to the Secret Number”] -[comparing-the-guess-to-the-secret-number] section of Chapter 2. +discussed in the [“Comparing the Guess to the Secret +Number”][comparing-the-guess-to-the-secret-number] section of +Chapter 2. Optionally, we can also include an `else` expression, which we chose to do here, to give the program an alternative block of code to execute should diff --git a/src/doc/book/src/ch04-02-references-and-borrowing.md b/src/doc/book/src/ch04-02-references-and-borrowing.md index b44aad3e50..27290fcf04 100644 --- a/src/doc/book/src/ch04-02-references-and-borrowing.md +++ b/src/doc/book/src/ch04-02-references-and-borrowing.md @@ -229,7 +229,7 @@ from under them! However, multiple immutable references are okay because no one who is just reading the data has the ability to affect anyone else’s reading of the data. -Note that a reference's scope starts from where it is introduced and continues +Note that a reference’s scope starts from where it is introduced and continues through the last time that reference is used. For instance, this code will compile because the last usage of the immutable references occurs before the mutable reference is introduced: @@ -252,7 +252,7 @@ println!("{}", r3); The scopes of the immutable references `r1` and `r2` end after the `println!` where they are last used, which is before the mutable reference `r3` is -created. These scopes don't overlap, so this code is allowed. +created. These scopes don’t overlap, so this code is allowed. Even though borrowing errors may be frustrating at times, remember that it’s the Rust compiler pointing out a potential bug early (at compile time rather diff --git a/src/doc/book/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md b/src/doc/book/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md index b4c0526406..241ddd2b09 100644 --- a/src/doc/book/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md +++ b/src/doc/book/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md @@ -1,7 +1,7 @@ # Managing Growing Projects with Packages, Crates, and Modules -As you write large programs, organizing your code is important because it’ll -become impossible to keep track of your entire program in your head. By +As you write large programs, organizing your code will be important because +keeping track of your entire program in your head will become impossible. By grouping related functionality and separating code with distinct features, you’ll clarify where to find code that implements a particular feature and where to go to change how a feature works. @@ -12,7 +12,7 @@ then multiple files. A package can contain multiple binary crates and optionally one library crate. As a package grows, you can extract parts into separate crates that become external dependencies. This chapter covers all these techniques. For very large projects of a set of interrelated packages -that evolve together, Cargo provides *workspaces*, which we’ll cover in the +that evolve together, Cargo provides workspaces, which we’ll cover in the [“Cargo Workspaces”][workspaces] section in Chapter 14. In addition to grouping functionality, encapsulating implementation details @@ -23,19 +23,18 @@ public for other code to use and which parts are private implementation details that you reserve the right to change. This is another way to limit the amount of detail you have to keep in your head. -A related aspect to organization and encapsulation is *scope*: the nested -context in which code is written has a set of names that are defined as “in -scope.” When reading, writing, and compiling code, programmers and compilers -need to know whether a particular name at a particular spot refers to a -variable, function, struct, enum, module, constant, or other item, and what -that item means. You can create scopes and change which names are in or out of -scope. You can’t have two items with the same name in the same scope; tools are -available to resolve name conflicts. +A related concept is scope: the nested context in which code is written has a +set of names that are defined as “in scope.” When reading, writing, and +compiling code, programmers and compilers need to know whether a particular +name at a particular spot refers to a variable, function, struct, enum, module, +constant, or other item and what that item means. You can create scopes and +change which names are in or out of scope. You can’t have two items with the +same name in the same scope; tools are available to resolve name conflicts. Rust has a number of features that allow you to manage your code’s -organization, including which details are exposed and which details are -private, and what names are in each scope in your programs. These features are -sometimes collectively referred to as the *module system* and include: +organization, including which details are exposed, which details are private, +and what names are in each scope in your programs. These features, sometimes +collectively referred to as the *module system*, and include: * **Packages:** A Cargo feature that lets you build, test, and share crates * **Crates:** A tree of modules that produces a library or executable diff --git a/src/doc/book/src/ch07-01-packages-and-crates.md b/src/doc/book/src/ch07-01-packages-and-crates.md index c731ec32cb..1b7a163af9 100644 --- a/src/doc/book/src/ch07-01-packages-and-crates.md +++ b/src/doc/book/src/ch07-01-packages-and-crates.md @@ -1,7 +1,7 @@ ## Packages and Crates -The first parts of the module system we’ll cover are *packages* and *crates*. A -*crate* is a binary or library. The *crate root* is a source file that the Rust +The first parts of the module system we’ll cover are packages and crates. A +crate is a binary or library. The *crate root* is a source file that the Rust compiler starts from and makes up the root module of your crate (we’ll explain modules in depth in the [“Defining Modules to Control Scope and Privacy”][modules]) section. A *package* is one or more crates @@ -43,10 +43,11 @@ in the *src/bin* directory: each file will be a separate binary crate. A crate will group related functionality together in a scope so the functionality is easy to share between multiple projects. For example, the -`rand` crate we used in Chapter 2 provides functionality that generates random -numbers. We can use that functionality in our own projects by bringing the -`rand` crate into our project’s scope. All the functionality provided by the -`rand` crate is accessible through the crate’s name, `rand`. +`rand` crate we used in [Chapter 2][rand] provides functionality +that generates random numbers. We can use that functionality in our own +projects by bringing the `rand` crate into our project’s scope. All the +functionality provided by the `rand` crate is accessible through the crate’s +name, `rand`. Keeping a crate’s functionality in its own scope clarifies whether particular functionality is defined in our crate or the `rand` crate and prevents @@ -60,3 +61,4 @@ our crate, it refers to the `struct Rng` that we defined. We would access the Let’s move on and talk about the module system! [modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html +[rand]: ch02-00-guessing-game-tutorial.html#generating-a-random-number diff --git a/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md index e52b293070..f6a9b15703 100644 --- a/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md +++ b/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md @@ -3,24 +3,24 @@ In this section, we’ll talk about modules and other parts of the module system, namely *paths* that allow you to name items; the `use` keyword that brings a path into scope; and the `pub` keyword to make items public. We’ll also discuss -using the `as` keyword, external packages, and the glob operator. For now, -let’s focus on modules! +the `as` keyword, external packages, and the glob operator. For now, let’s +focus on modules! *Modules* let us organize code within a crate into groups for readability and easy reuse. Modules also control the *privacy* of items, which is whether an -item can be used by outside code (*public*) or whether it’s an internal -implementation detail and not available for outside use (*private*). +item can be used by outside code (*public*) or is an internal implementation +detail and not available for outside use (*private*). As an example, let’s write a library crate that provides the functionality of a restaurant. We’ll define the signatures of functions but leave their bodies -empty to concentrate on the organization of the code rather than actually -implementing a restaurant in code. +empty to concentrate on the organization of the code, rather than actually +implement a restaurant in code. -In the restaurant industry, parts of a restaurant are referred to as *front of -house* and others as *back of house*. Front of house is where customers are and -includes hosts seating customers, servers taking orders and payment, and -bartenders making drinks. Back of house includes the chefs and cooks in the -kitchen, dishwashers cleaning up, and managers doing administrative work. +In the restaurant industry, some parts of a restaurant are referred to as +*front of house* and others as *back of house*. Front of house is where +customers are; this is where hosts seat customers, servers take orders and +payment, and bartenders make drinks. Back of house is where the chefs and cooks +work in the kitchen, dishwashers clean up, and managers do administrative work. To structure our crate in the same way that a real restaurant works, we can organize the functions into nested modules. Create a new library named @@ -50,22 +50,22 @@ mod front_of_house { Listing 7-1: A `front_of_house` module containing other modules that then contain functions -We define a module by starting with the `mod` keyword, and then specify the +We define a module by starting with the `mod` keyword and then specify the name of the module (in this case, `front_of_house`) and place curly brackets around the body of the module. Inside modules, we can have other modules, as in this case with the modules `hosting` and `serving`. Modules can also hold -definitions for other items, such as structs, enums, constants, traits, or as -in Listing 7-1, functions. +definitions for other items, such as structs, enums, constants, traits, or—as +in Listing 7-1—functions. By using modules, we can group related definitions together and name why they’re related. Programmers using this code would have an easier time finding -the definitions they want to use because they could navigate the code based on -the groups rather than having to read through all the definitions. Programmers -adding new functionality to this code would know where to place the code to -keep the program organized. +the definitions they wanted to use because they could navigate the code based +on the groups rather than having to read through all the definitions. +Programmers adding new functionality to this code would know where to place the +code to keep the program organized. -Earlier, we mentioned that *src/main.rs* and *src/lib.rs* are called *crate -roots*. The reason for their name is that the contents of either of these two +Earlier, we mentioned that *src/main.rs* and *src/lib.rs* are called crate +roots. The reason for their name is that the contents of either of these two files form a module named `crate` at the root of the crate’s module structure, known as the *module tree*. @@ -86,12 +86,12 @@ crate Listing 7-2: The module tree for the code in Listing 7-1 -This tree shows how some of the modules nest inside one another (such as -`hosting` nests inside `front_of_house`). The tree also shows how some modules +This tree shows how some of the modules nest inside one another (for example, +`hosting` nests inside `front_of_house`). The tree also shows that some modules are *siblings* to each other, meaning they’re defined in the same module (`hosting` and `serving` are defined within `front_of_house`). To continue the family metaphor, if module A is contained inside module B, we say that module A -is the *child* of module B, and that module B is the *parent* of module A. +is the *child* of module B and that module B is the *parent* of module A. Notice that the entire module tree is rooted under the implicit module named `crate`. diff --git a/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md index 9cc52ade7c..8cb0dfadc4 100644 --- a/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md +++ b/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md @@ -1,10 +1,10 @@ ## Paths for Referring to an Item in the Module Tree -To show Rust where to find an item in a module tree, we use a *path* in the -same way we use a path when navigating a filesystem. If we want to call a -function, we need to know its path. +To show Rust where to find an item in a module tree, we use a path in the same +way we use a path when navigating a filesystem. If we want to call a function, +we need to know its path. -A *path* can take two forms: +A path can take two forms: * An *absolute path* starts from a crate root by using a crate name or a literal `crate`. @@ -19,11 +19,12 @@ Let’s return to the example in Listing 7-1. How do we call the `add_to_waitlist` function? In Listing 7-3, we simplified our code a bit by removing some of the modules and functions. We’ll show two ways to call the `add_to_waitlist` function from a new function `eat_at_restaurant` defined in -the crate root. The `eat_at_restaurant` function is part of our library crate's -public API, so we mark it with the `pub` keyword. In the ["Exposing Paths with -the `pub` Keyword"][pub] section, we'll go into more detail -about `pub`. Note that this example won’t compile just yet; we’ll explain why -in a bit. +the crate root. The `eat_at_restaurant` function is part of our library crate’s +public API, so we mark it with the `pub` keyword. In the [”Exposing Paths with +the `pub` Keyword”][pub] section, we’ll go into more detail +about `pub`. + +Note that this example won’t compile just yet; we’ll explain why in a bit. Filename: src/lib.rs @@ -103,7 +104,7 @@ have the correct paths for the `hosting` module and the `add_to_waitlist` function, but Rust won’t let us use them because it doesn’t have access to the private sections. -Modules aren’t only useful for organizing your code, they also define Rust’s +Modules aren’t useful only for organizing your code. They also define Rust’s *privacy boundary*: the line that encapsulates the implementation details external code isn’t allowed to know about, call, or rely on. So, if you want to make an item like a function or struct private, you put it in a module. @@ -114,15 +115,15 @@ can’t use the private items inside child modules, but items in child modules can use the items in their ancestor modules. The reason is that child modules wrap and hide their implementation details, but the child modules can see the context in which they’re defined. To continue with the restaurant metaphor, -think of the privacy rules like the back office of a restaurant: what goes on -in there is private to restaurant customers, but office managers can see and do -everything in the restaurant in which they operate. +think of the privacy rules as being like the back office of a restaurant: what +goes on in there is private to restaurant customers, but office managers can +see and do everything in the restaurant in which they operate. Rust chose to have the module system function this way so that hiding inner implementation details is the default. That way, you know which parts of the inner code you can change without breaking outer code. But you can expose inner -parts of child modules code to outer ancestor modules by making an item public -using the `pub` keyword. +parts of child modules code to outer ancestor modules by using the `pub` +keyword to make an item public. ### Exposing Paths with the `pub` Keyword @@ -210,8 +211,8 @@ pub fn eat_at_restaurant() { and `fn add_to_waitlist` lets us call the function from `eat_at_restaurant` -Now the code will compile! Let’s look at the absolute and the relative path, -and double-check why adding the `pub` keyword lets us use these paths in +Now the code will compile! Let’s look at the absolute and the relative path and +double-check why adding the `pub` keyword lets us use these paths in `add_to_waitlist` with respect to the privacy rules. In the absolute path, we start with `crate`, the root of our crate’s module @@ -229,7 +230,7 @@ first step: rather than starting from the crate root, the path starts from `front_of_house`. The `front_of_house` module is defined within the same module as `eat_at_restaurant`, so the relative path starting from the module in which `eat_at_restaurant` is defined works. Then, because `hosting` and -`add_to_waitlist` are marked with `pub`, the rest of the path works and this +`add_to_waitlist` are marked with `pub`, the rest of the path works, and this function call is valid! ### Starting Relative Paths with `super` @@ -329,7 +330,7 @@ Also, note that because `back_of_house::Breakfast` has a private field, the struct needs to provide a public associated function that constructs an instance of `Breakfast` (we’ve named it `summer` here). If `Breakfast` didn’t have such a function, we couldn’t create an instance of `Breakfast` in -`eat_at_restaurant` because we can’t set the value of the private +`eat_at_restaurant` because we couldn’t set the value of the private `seasonal_fruit` field in `eat_at_restaurant`. In contrast, if we make an enum public, all of its variants are then public. We diff --git a/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md index 257f68ce9d..3fcdb4bbe2 100644 --- a/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md +++ b/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md @@ -44,7 +44,7 @@ also check privacy, like any other paths. Specifying a relative path with `use` is slightly different. Instead of starting from a name in the current scope, we must start the path given to `use` with the keyword `self`. Listing 7-12 shows how to specify a relative -path to get the same behavior as Listing 7-11. +path to get the same behavior as in Listing 7-11. Filename: src/lib.rs @@ -227,11 +227,11 @@ from a new scope with `pub use` By using `pub use`, external code can now call the `add_to_waitlist` function using `hosting::add_to_waitlist`. If we hadn’t specified `pub use`, the -`eat_at_restaurant` function could call `hosting::add_to_waitlist` in its scope -but external code couldn’t take advantage of this new path. +`eat_at_restaurant` function could call `hosting::add_to_waitlist` in its +scope, but external code couldn’t take advantage of this new path. Re-exporting is useful when the internal structure of your code is different -than the way programmers calling your code would think about the domain. For +from how programmers calling your code would think about the domain. For example, in this restaurant metaphor, the people running the restaurant think about “front of house” and “back of house.” But customers visiting a restaurant probably won’t think about the parts of the restaurant in those terms. With @@ -253,11 +253,11 @@ rand = "0.5.5" ``` Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the -`rand` package and any dependencies from *https://crates.io* and make `rand` -available to our project. +`rand` package and any dependencies from [crates.io](https://crates.io/) and +make `rand` available to our project. Then, to bring `rand` definitions into the scope of our package, we added a -`use` line starting with the name of the package, `rand`, and listing the items +`use` line starting with the name of the package, `rand`, and listed the items we wanted to bring into scope. Recall that in the [“Generating a Random Number”][rand] section in Chapter 2, we brought the `Rng` trait into scope and called the `rand::thread_rng` function: @@ -270,9 +270,9 @@ fn main() { ``` Members of the Rust community have made many packages available at -*https://crates.io*, and pulling any of them into your package involves these -same steps: listing them in your package’s *Cargo.toml* file and using `use` to -bring items into scope. +[crates.io](https://crates.io/), and pulling any of them into your package +involves these same steps: listing them in your package’s *Cargo.toml* file and +using `use` to bring items into scope. Note that the standard library (`std`) is also a crate that’s external to our package. Because the standard library is shipped with the Rust language, we diff --git a/src/doc/book/src/ch08-02-strings.md b/src/doc/book/src/ch08-02-strings.md index f36cf5e161..f09ebbb98e 100644 --- a/src/doc/book/src/ch08-02-strings.md +++ b/src/doc/book/src/ch08-02-strings.md @@ -436,7 +436,7 @@ than 1 byte. Getting grapheme clusters from strings is complex, so this functionality is not provided by the standard library. Crates are available on -[crates.io](https://crates.io) if this is the functionality you need. +[crates.io](https://crates.io/) if this is the functionality you need. ### Strings Are Not So Simple diff --git a/src/doc/book/src/ch08-03-hash-maps.md b/src/doc/book/src/ch08-03-hash-maps.md index d1db52042d..f140805d71 100644 --- a/src/doc/book/src/ch08-03-hash-maps.md +++ b/src/doc/book/src/ch08-03-hash-maps.md @@ -100,8 +100,9 @@ they’ve been moved into the hash map with the call to `insert`. If we insert references to values into the hash map, the values won’t be moved into the hash map. The values that the references point to must be valid for at least as long as the hash map is valid. We’ll talk more about these issues in -the [“Validating References with Lifetimes”] -[validating-references-with-lifetimes] section in Chapter 10. +the [“Validating References with +Lifetimes”][validating-references-with-lifetimes] section in +Chapter 10. ### Accessing Values in a Hash Map @@ -271,7 +272,7 @@ purposes, you can switch to another function by specifying a different *hasher*. A hasher is a type that implements the `BuildHasher` trait. We’ll talk about traits and how to implement them in Chapter 10. You don’t necessarily have to implement your own hasher from scratch; -[crates.io](https://crates.io) has libraries shared by other Rust users that +[crates.io](https://crates.io/) has libraries shared by other Rust users that provide hashers implementing many common hashing algorithms. [^siphash]: [https://www.131002.net/siphash/siphash.pdf](https://www.131002.net/siphash/siphash.pdf) diff --git a/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md b/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md index 906b8e7f0f..454b78071d 100644 --- a/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md +++ b/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md @@ -192,9 +192,9 @@ you’ll need to figure out what action the code is taking with what values to cause the panic and what the code should do instead. We’ll come back to `panic!` and when we should and should not use `panic!` to -handle error conditions in the [“To `panic!` or Not to `panic!`”] -[to-panic-or-not-to-panic] section later in this chapter. Next, -we’ll look at how to recover from an error using `Result`. +handle error conditions in the [“To `panic!` or Not to +`panic!`”][to-panic-or-not-to-panic] section later in this +chapter. Next, we’ll look at how to recover from an error using `Result`. [to-panic-or-not-to-panic]: ch09-03-to-panic-or-not-to-panic.html#to-panic-or-not-to-panic diff --git a/src/doc/book/src/ch10-02-traits.md b/src/doc/book/src/ch10-02-traits.md index 131f6c1928..8fcf15df01 100644 --- a/src/doc/book/src/ch10-02-traits.md +++ b/src/doc/book/src/ch10-02-traits.md @@ -480,13 +480,14 @@ error[E0507]: cannot move out of borrowed content The key line in this error is `cannot move out of type [T], a non-copy slice`. With our non-generic versions of the `largest` function, we were only trying to -find the largest `i32` or `char`. As discussed in the [“Stack-Only Data: Copy”] -[stack-only-data-copy] section in Chapter 4, types like `i32` -and `char` that have a known size can be stored on the stack, so they implement -the `Copy` trait. But when we made the `largest` function generic, it became -possible for the `list` parameter to have types in it that don’t implement the -`Copy` trait. Consequently, we wouldn’t be able to move the value out of -`list[0]` and into the `largest` variable, resulting in this error. +find the largest `i32` or `char`. As discussed in the [“Stack-Only Data: +Copy”][stack-only-data-copy] section in Chapter 4, types like +`i32` and `char` that have a known size can be stored on the stack, so they +implement the `Copy` trait. But when we made the `largest` function generic, +it became possible for the `list` parameter to have types in it that don’t +implement the `Copy` trait. Consequently, we wouldn’t be able to move the +value out of `list[0]` and into the `largest` variable, resulting in this +error. To call this code with only those types that implement the `Copy` trait, we can add `Copy` to the trait bounds of `T`! Listing 10-15 shows the complete code of diff --git a/src/doc/book/src/ch10-03-lifetime-syntax.md b/src/doc/book/src/ch10-03-lifetime-syntax.md index 893d9ba6fc..383a4ec40e 100644 --- a/src/doc/book/src/ch10-03-lifetime-syntax.md +++ b/src/doc/book/src/ch10-03-lifetime-syntax.md @@ -1,14 +1,15 @@ ## Validating References with Lifetimes -One detail we didn’t discuss in the [“References and Borrowing”] -[references-and-borrowing] section in Chapter 4 is that every -reference in Rust has a *lifetime*, which is the scope for which that reference -is valid. Most of the time, lifetimes are implicit and inferred, just like most -of the time, types are inferred. We must annotate types when multiple types are -possible. In a similar way, we must annotate lifetimes when the lifetimes of -references could be related in a few different ways. Rust requires us to -annotate the relationships using generic lifetime parameters to ensure the -actual references used at runtime will definitely be valid. +One detail we didn’t discuss in the [“References and +Borrowing”][references-and-borrowing] section in Chapter 4 is +that every reference in Rust has a *lifetime*, which is the scope for which +that reference is valid. Most of the time, lifetimes are implicit and +inferred, just like most of the time, types are inferred. We must annotate +types when multiple types are possible. In a similar way, we must annotate +lifetimes when the lifetimes of references could be related in a few different +ways. Rust requires us to annotate the relationships using generic lifetime +parameters to ensure the actual references used at runtime will definitely be +valid. The concept of lifetimes is somewhat different from tools in other programming languages, arguably making lifetimes Rust’s most distinctive feature. Although diff --git a/src/doc/book/src/ch11-01-writing-tests.md b/src/doc/book/src/ch11-01-writing-tests.md index 6676fdfd7d..b5c645f34c 100644 --- a/src/doc/book/src/ch11-01-writing-tests.md +++ b/src/doc/book/src/ch11-01-writing-tests.md @@ -105,8 +105,8 @@ reads `1 passed; 0 failed` totals the number of tests that passed or failed. Because we don’t have any tests we’ve marked as ignored, the summary shows `0 ignored`. We also haven’t filtered the tests being run, so the end of the summary shows `0 filtered out`. We’ll talk about ignoring and filtering out -tests in the next section, [“Controlling How Tests Are Run.”] -[controlling-how-tests-are-run] +tests in the next section, [“Controlling How Tests Are +Run.”][controlling-how-tests-are-run] The `0 measured` statistic is for benchmark tests that measure performance. Benchmark tests are, as of this writing, only available in nightly Rust. See @@ -509,12 +509,12 @@ optional arguments to the `assert!`, `assert_eq!`, and `assert_ne!` macros. Any arguments specified after the one required argument to `assert!` or the two required arguments to `assert_eq!` and `assert_ne!` are passed along to the `format!` macro (discussed in Chapter 8 in the [“Concatenation with the `+` -Operator or the `format!` Macro”] -[concatenation-with-the--operator-or-the-format-macro] section), -so you can pass a format string that contains `{}` placeholders and values to -go in those placeholders. Custom messages are useful to document what an -assertion means; when a test fails, you’ll have a better idea of what the -problem is with the code. +Operator or the `format!` +Macro”][concatenation-with-the--operator-or-the-format-macro] +section), so you can pass a format string that contains `{}` placeholders and +values to go in those placeholders. Custom messages are useful to document +what an assertion means; when a test fails, you’ll have a better idea of what +the problem is with the code. For example, let’s say we have a function that greets people by name and we want to test that the name we pass into the function appears in the output: diff --git a/src/doc/book/src/ch12-01-accepting-command-line-arguments.md b/src/doc/book/src/ch12-01-accepting-command-line-arguments.md index 50d17ae5d1..5f4f61e88c 100644 --- a/src/doc/book/src/ch12-01-accepting-command-line-arguments.md +++ b/src/doc/book/src/ch12-01-accepting-command-line-arguments.md @@ -20,7 +20,7 @@ $ cargo run searchstring example-filename.txt ``` Right now, the program generated by `cargo new` cannot process arguments we -give it. Some existing libraries on [Crates.io](https://crates.io/) can help +give it. Some existing libraries on [crates.io](https://crates.io/) can help with writing a program that accepts command line arguments, but because you’re just learning this concept, let’s implement this capability ourselves. diff --git a/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md b/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md index 5f014d7f98..d26c590049 100644 --- a/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md @@ -187,14 +187,15 @@ trade-off. > ### The Trade-Offs of Using `clone` > > There’s a tendency among many Rustaceans to avoid using `clone` to fix -> ownership problems because of its runtime cost. In [Chapter 13][ch13], you’ll learn how to use more efficient methods in this type of -> situation. But for now, it’s okay to copy a few strings to continue making -> progress because you’ll make these copies only once and your filename and -> query string are very small. It’s better to have a working program that’s a -> bit inefficient than to try to hyperoptimize code on your first pass. As you -> become more experienced with Rust, it’ll be easier to start with the most -> efficient solution, but for now, it’s perfectly acceptable to call `clone`. +> ownership problems because of its runtime cost. In +> [Chapter 13][ch13], you’ll learn how to use more efficient +> methods in this type of situation. But for now, it’s okay to copy a few +> strings to continue making progress because you’ll make these copies only +> once and your filename and query string are very small. It’s better to have +> a working program that’s a bit inefficient than to try to hyperoptimize code +> on your first pass. As you become more experienced with Rust, it’ll be +> easier to start with the most efficient solution, but for now, it’s +> perfectly acceptable to call `clone`. We’ve updated `main` so it places the instance of `Config` returned by `parse_config` into a variable named `config`, and we updated the code that diff --git a/src/doc/book/src/ch14-00-more-about-cargo.md b/src/doc/book/src/ch14-00-more-about-cargo.md index d5904b2f68..d08d8cc7ce 100644 --- a/src/doc/book/src/ch14-00-more-about-cargo.md +++ b/src/doc/book/src/ch14-00-more-about-cargo.md @@ -5,9 +5,9 @@ our code, but it can do a lot more. In this chapter, we’ll discuss some of its other, more advanced features to show you how to do the following: * Customize your build through release profiles -* Publish libraries on [crates.io](https://crates.io) +* Publish libraries on [crates.io](https://crates.io/) * Organize large projects with workspaces -* Install binaries from [crates.io](https://crates.io) +* Install binaries from [crates.io](https://crates.io/) * Extend Cargo using custom commands Cargo can do even more than what we cover in this chapter, so for a full diff --git a/src/doc/book/src/ch14-02-publishing-to-crates-io.md b/src/doc/book/src/ch14-02-publishing-to-crates-io.md index 69d0d54a37..f1b10f7c95 100644 --- a/src/doc/book/src/ch14-02-publishing-to-crates-io.md +++ b/src/doc/book/src/ch14-02-publishing-to-crates-io.md @@ -1,9 +1,9 @@ ## Publishing a Crate to Crates.io -We’ve used packages from [crates.io](https://crates.io) as +We’ve used packages from [crates.io](https://crates.io/) as dependencies of our project, but you can also share your code with other people by publishing your own packages. The crate registry at -[crates.io](https://crates.io) distributes the source code of +[crates.io](https://crates.io/) distributes the source code of your packages, so it primarily hosts code that is open source. Rust and Cargo have features that help make your published package easier for @@ -337,8 +337,8 @@ differs from their public API. ### Setting Up a Crates.io Account Before you can publish any crates, you need to create an account on -[crates.io](https://crates.io) and get an API token. To do so, -visit the home page at [crates.io](https://crates.io) and log in +[crates.io](https://crates.io/) and get an API token. To do so, +visit the home page at [crates.io](https://crates.io/) and log in via a GitHub account. (The GitHub account is currently a requirement, but the site might support other ways of creating an account in the future.) Once you’re logged in, visit your account settings at @@ -352,7 +352,7 @@ $ cargo login abcdefghijklmnopqrstuvwxyz012345 This command will inform Cargo of your API token and store it locally in *~/.cargo/credentials*. Note that this token is a *secret*: do not share it with anyone else. If you do share it with anyone for any reason, you should -revoke it and generate a new token on [crates.io](https://crates.io). ### Adding Metadata to a New Crate @@ -363,7 +363,7 @@ to the `[package]` section of the crate’s *Cargo.toml* file. Your crate will need a unique name. While you’re working on a crate locally, you can name a crate whatever you’d like. However, crate names on -[crates.io](https://crates.io) are allocated on a first-come, +[crates.io](https://crates.io/) are allocated on a first-come, first-served basis. Once a crate name is taken, no one else can publish a crate with that name. Before attempting to publish a crate, search for the name you want to use on the site. If the name has been used by another crate, you will @@ -449,13 +449,13 @@ easily. Now that you’ve created an account, saved your API token, chosen a name for your crate, and specified the required metadata, you’re ready to publish! Publishing a crate uploads a specific version to -[crates.io](https://crates.io) for others to use. +[crates.io](https://crates.io/) for others to use. Be careful when publishing a crate because a publish is *permanent*. The version can never be overwritten, and the code cannot be deleted. One major -goal of [crates.io](https://crates.io) is to act as a permanent +goal of [crates.io](https://crates.io/) is to act as a permanent archive of code so that builds of all projects that depend on crates from -[crates.io](https://crates.io) will continue to work. Allowing +[crates.io](https://crates.io/) will continue to work. Allowing version deletions would make fulfilling that goal impossible. However, there is no limit to the number of crate versions you can publish. diff --git a/src/doc/book/src/ch14-03-cargo-workspaces.md b/src/doc/book/src/ch14-03-cargo-workspaces.md index 30255aca59..8b8c078baf 100644 --- a/src/doc/book/src/ch14-03-cargo-workspaces.md +++ b/src/doc/book/src/ch14-03-cargo-workspaces.md @@ -320,11 +320,11 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out This output shows `cargo test` only ran the tests for the `add-one` crate and didn’t run the `adder` crate tests. -If you publish the crates in the workspace to *https://crates.io/*, each crate -in the workspace will need to be published separately. The `cargo publish` -command does not have an `--all` flag or a `-p` flag, so you must change to -each crate’s directory and run `cargo publish` on each crate in the workspace -to publish the crates. +If you publish the crates in the workspace to [crates.io](https://crates.io/), +each crate in the workspace will need to be published separately. The `cargo +publish` command does not have an `--all` flag or a `-p` flag, so you must +change to each crate’s directory and run `cargo publish` on each crate in the +workspace to publish the crates. For additional practice, add an `add-two` crate to this workspace in a similar way as the `add-one` crate! diff --git a/src/doc/book/src/ch14-04-installing-binaries.md b/src/doc/book/src/ch14-04-installing-binaries.md index 826b970dd1..a654a371ac 100644 --- a/src/doc/book/src/ch14-04-installing-binaries.md +++ b/src/doc/book/src/ch14-04-installing-binaries.md @@ -3,7 +3,7 @@ The `cargo install` command allows you to install and use binary crates locally. This isn’t intended to replace system packages; it’s meant to be a convenient way for Rust developers to install tools that others have shared on -[crates.io](https://crates.io). Note that you can only install +[crates.io](https://crates.io/). Note that you can only install packages that have binary targets. A *binary target* is the runnable program that is created if the crate has a *src/main.rs* file or another file specified as a binary, as opposed to a library target that isn’t runnable on its own but diff --git a/src/doc/book/src/ch14-05-extending-cargo.md b/src/doc/book/src/ch14-05-extending-cargo.md index d70d227655..bd228714ae 100644 --- a/src/doc/book/src/ch14-05-extending-cargo.md +++ b/src/doc/book/src/ch14-05-extending-cargo.md @@ -9,9 +9,9 @@ built-in Cargo tools is a super convenient benefit of Cargo’s design! ## Summary -Sharing code with Cargo and [crates.io](https://crates.io) is +Sharing code with Cargo and [crates.io](https://crates.io/) is part of what makes the Rust ecosystem useful for many different tasks. Rust’s standard library is small and stable, but crates are easy to share, use, and improve on a timeline different from that of the language. Don’t be shy about -sharing code that’s useful to you on [crates.io](https://crates.io); it’s likely that it will be useful to someone else as well! diff --git a/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md b/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md index 7ec5d793a7..ff9830e38c 100644 --- a/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md +++ b/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md @@ -42,8 +42,8 @@ The smart pointer `Rc` is also not `Sync` for the same reasons that it’s no family of related `Cell` types are not `Sync`. The implementation of borrow checking that `RefCell` does at runtime is not thread-safe. The smart pointer `Mutex` is `Sync` and can be used to share access with multiple -threads as you saw in the [“Sharing a `Mutex` Between Multiple Threads”] -[sharing-a-mutext-between-multiple-threads] section. +threads as you saw in the [“Sharing a `Mutex` Between Multiple +Threads”][sharing-a-mutext-between-multiple-threads] section. ### Implementing `Send` and `Sync` Manually Is Unsafe diff --git a/src/doc/book/src/ch17-02-trait-objects.md b/src/doc/book/src/ch17-02-trait-objects.md index b9342ac231..6145f21c52 100644 --- a/src/doc/book/src/ch17-02-trait-objects.md +++ b/src/doc/book/src/ch17-02-trait-objects.md @@ -331,17 +331,17 @@ didn’t mean to pass and we should pass a different type or we should implement ### Trait Objects Perform Dynamic Dispatch -Recall in the [“Performance of Code Using Generics”] -[performance-of-code-using-generics] section in Chapter 10 our -discussion on the monomorphization process performed by the compiler when we -use trait bounds on generics: the compiler generates nongeneric implementations -of functions and methods for each concrete type that we use in place of a -generic type parameter. The code that results from monomorphization is doing -*static dispatch*, which is when the compiler knows what method you’re calling -at compile time. This is opposed to *dynamic dispatch*, which is when the -compiler can’t tell at compile time which method you’re calling. In dynamic -dispatch cases, the compiler emits code that at runtime will figure out which -method to call. +Recall in the [“Performance of Code Using +Generics”][performance-of-code-using-generics] section in +Chapter 10 our discussion on the monomorphization process performed by the +compiler when we use trait bounds on generics: the compiler generates +nongeneric implementations of functions and methods for each concrete type +that we use in place of a generic type parameter. The code that results from +monomorphization is doing *static dispatch*, which is when the compiler knows +what method you’re calling at compile time. This is opposed to *dynamic +dispatch*, which is when the compiler can’t tell at compile time which method +you’re calling. In dynamic dispatch cases, the compiler emits code that at +runtime will figure out which method to call. When we use trait objects, Rust must use dynamic dispatch. The compiler doesn’t know all the types that might be used with the code that is using trait diff --git a/src/doc/book/src/ch18-01-all-the-places-for-patterns.md b/src/doc/book/src/ch18-01-all-the-places-for-patterns.md index f14e0c9ed8..d838532fba 100644 --- a/src/doc/book/src/ch18-01-all-the-places-for-patterns.md +++ b/src/doc/book/src/ch18-01-all-the-places-for-patterns.md @@ -28,8 +28,9 @@ value can never fail and thus covers every remaining case. A particular pattern `_` will match anything, but it never binds to a variable, so it’s often used in the last match arm. The `_` pattern can be useful when you want to ignore any value not specified, for example. We’ll cover the `_` -pattern in more detail in the [“Ignoring Values in a Pattern”] -[ignoring-values-in-a-pattern] section later in this chapter. +pattern in more detail in the [“Ignoring Values in a +Pattern”][ignoring-values-in-a-pattern] section later in this +chapter. ### Conditional `if let` Expressions @@ -229,11 +230,11 @@ error[E0308]: mismatched types ``` If we wanted to ignore one or more of the values in the tuple, we could use `_` -or `..`, as you’ll see in the [“Ignoring Values in a Pattern”] -[ignoring-values-in-a-pattern] section. If the problem is that -we have too many variables in the pattern, the solution is to make the types -match by removing variables so the number of variables equals the number of -elements in the tuple. +or `..`, as you’ll see in the [“Ignoring Values in a +Pattern”][ignoring-values-in-a-pattern] section. If the problem +is that we have too many variables in the pattern, the solution is to make the +types match by removing variables so the number of variables equals the number +of elements in the tuple. ### Function Parameters diff --git a/src/doc/book/src/ch19-01-unsafe-rust.md b/src/doc/book/src/ch19-01-unsafe-rust.md index 04ee039f3f..8605ede6a2 100644 --- a/src/doc/book/src/ch19-01-unsafe-rust.md +++ b/src/doc/book/src/ch19-01-unsafe-rust.md @@ -437,16 +437,15 @@ fn main() { Listing 19-9: Defining and using an immutable static variable - - Static variables are similar to constants, which we discussed in the -[“Differences Between Variables and Constants”] -[differences-between-variables-and-constants] section in -Chapter 3. The names of static variables are in `SCREAMING_SNAKE_CASE` by -convention, and we *must* annotate the variable’s type, which is `&'static str` -in this example. Static variables can only store references with the `'static` -lifetime, which means the Rust compiler can figure out the lifetime; we don’t -need to annotate it explicitly. Accessing an immutable static variable is safe. +[“Differences Between Variables and +Constants”][differences-between-variables-and-constants] +section in Chapter 3. The names of static variables are in +`SCREAMING_SNAKE_CASE` by convention, and we *must* annotate the variable’s +type, which is `&'static str` in this example. Static variables can only store +references with the `'static` lifetime, which means the Rust compiler can +figure out the lifetime; we don’t need to annotate it explicitly. Accessing an +immutable static variable is safe. Constants and immutable static variables might seem similar, but a subtle difference is that values in a static variable have a fixed address in memory. @@ -518,15 +517,15 @@ By using `unsafe impl`, we’re promising that we’ll uphold the invariants tha the compiler can’t verify. As an example, recall the `Sync` and `Send` marker traits we discussed in the -[“Extensible Concurrency with the `Sync` and `Send` Traits”] -[extensible-concurrency-with-the-sync-and-send-traits] section -in Chapter 16: the compiler implements these traits automatically if our types -are composed entirely of `Send` and `Sync` types. If we implement a type that -contains a type that is not `Send` or `Sync`, such as raw pointers, and we want -to mark that type as `Send` or `Sync`, we must use `unsafe`. Rust can’t verify -that our type upholds the guarantees that it can be safely sent across threads -or accessed from multiple threads; therefore, we need to do those checks -manually and indicate as such with `unsafe`. +[“Extensible Concurrency with the `Sync` and `Send` +Traits”][extensible-concurrency-with-the-sync-and-send-traits] +section in Chapter 16: the compiler implements these traits automatically if +our types are composed entirely of `Send` and `Sync` types. If we implement a +type that contains a type that is not `Send` or `Sync`, such as raw pointers, +and we want to mark that type as `Send` or `Sync`, we must use `unsafe`. Rust +can’t verify that our type upholds the guarantees that it can be safely sent +across threads or accessed from multiple threads; therefore, we need to do +those checks manually and indicate as such with `unsafe`. ### When to Use Unsafe Code diff --git a/src/doc/book/src/ch19-03-advanced-traits.md b/src/doc/book/src/ch19-03-advanced-traits.md index 288777057e..c959f231dc 100644 --- a/src/doc/book/src/ch19-03-advanced-traits.md +++ b/src/doc/book/src/ch19-03-advanced-traits.md @@ -1,9 +1,9 @@ ## Advanced Traits -We first covered traits in the [“Traits: Defining Shared Behavior”] -[traits-defining-shared-behavior] section of Chapter 10, but as -with lifetimes, we didn’t discuss the more advanced details. Now that you know -more about Rust, we can get into the nitty-gritty. +We first covered traits in the [“Traits: Defining Shared +Behavior”][traits-defining-shared-behavior] section of Chapter +10, but as with lifetimes, we didn’t discuss the more advanced details. Now +that you know more about Rust, we can get into the nitty-gritty. ### Specifying Placeholder Types in Trait Definitions with Associated Types @@ -22,10 +22,10 @@ the other features discussed in this chapter. One example of a trait with an associated type is the `Iterator` trait that the standard library provides. The associated type is named `Item` and stands in for the type of the values the type implementing the `Iterator` trait is -iterating over. In [“The `Iterator` Trait and the `next` Method”] -[the-iterator-trait-and-the-next-method] section of Chapter 13, -we mentioned that the definition of the `Iterator` trait is as shown in Listing -19-12. +iterating over. In [“The `Iterator` Trait and the `next` +Method”][the-iterator-trait-and-the-next-method] section of +Chapter 13, we mentioned that the definition of the `Iterator` trait is as +shown in Listing 19-12. ```rust pub trait Iterator { @@ -621,19 +621,19 @@ it within an outline of asterisks. ### Using the Newtype Pattern to Implement External Traits on External Types -In Chapter 10 in the [“Implementing a Trait on a Type”] -[implementing-a-trait-on-a-type] section, we mentioned the -orphan rule that states we’re allowed to implement a trait on a type as long as -either the trait or the type are local to our crate. It’s possible to get -around this restriction using the *newtype pattern*, which involves creating a -new type in a tuple struct. (We covered tuple structs in the [“Using Tuple -Structs without Named Fields to Create Different Types”][tuple-structs] section of Chapter 5.) The tuple struct will have one field and be a -thin wrapper around the type we want to implement a trait for. Then the wrapper -type is local to our crate, and we can implement the trait on the wrapper. -*Newtype* is a term that originates from the Haskell programming language. -There is no runtime performance penalty for using this pattern, and the wrapper -type is elided at compile time. +In Chapter 10 in the [“Implementing a Trait on a +Type”][implementing-a-trait-on-a-type] section, we mentioned +the orphan rule that states we’re allowed to implement a trait on a type as +long as either the trait or the type are local to our crate. It’s possible to +get around this restriction using the *newtype pattern*, which involves +creating a new type in a tuple struct. (We covered tuple structs in the +[“Using Tuple Structs without Named Fields to Create Different +Types”][tuple-structs] section of Chapter 5.) The tuple struct +will have one field and be a thin wrapper around the type we want to implement +a trait for. Then the wrapper type is local to our crate, and we can implement +the trait on the wrapper. *Newtype* is a term that originates from the Haskell +programming language. There is no runtime performance penalty for using this +pattern, and the wrapper type is elided at compile time. As an example, let’s say we want to implement `Display` on `Vec`, which the orphan rule prevents us from doing directly because the `Display` trait and the diff --git a/src/doc/book/src/ch19-04-advanced-types.md b/src/doc/book/src/ch19-04-advanced-types.md index 97ea1bb17b..e1e46b1ed1 100644 --- a/src/doc/book/src/ch19-04-advanced-types.md +++ b/src/doc/book/src/ch19-04-advanced-types.md @@ -32,9 +32,9 @@ public API we provide, such as a method to add a name string to the `People` collection; that code wouldn’t need to know that we assign an `i32` ID to names internally. The newtype pattern is a lightweight way to achieve encapsulation to hide implementation details, which we discussed in the [“Encapsulation that -Hides Implementation Details”] -[encapsulation-that-hides-implementation-details] section of -Chapter 17. +Hides Implementation +Details”][encapsulation-that-hides-implementation-details] +section of Chapter 17. ### Creating Type Synonyms with Type Aliases @@ -308,11 +308,11 @@ We can combine `str` with all kinds of pointers: for example, `Box` or `Rc`. In fact, you’ve seen this before but with a different dynamically sized type: traits. Every trait is a dynamically sized type we can refer to by using the name of the trait. In Chapter 17 in the [“Using Trait Objects That -Allow for Values of Different Types”] -[using-trait-objects-that-allow-for-values-of-different-types] -section, we mentioned that to use traits as trait objects, we must put them -behind a pointer, such as `&dyn Trait` or `Box` (`Rc` -would work too). +Allow for Values of Different +Types”][using-trait-objects-that-allow-for-values-of-different-types] section, we mentioned that to use traits as trait objects, we must +put them behind a pointer, such as `&dyn Trait` or `Box` (`Rc` would work too). To work with DSTs, Rust has a particular trait called the `Sized` trait to determine whether or not a type’s size is known at compile time. This trait is diff --git a/src/doc/book/src/ch19-05-advanced-functions-and-closures.md b/src/doc/book/src/ch19-05-advanced-functions-and-closures.md index a40e222e3d..2955114afc 100644 --- a/src/doc/book/src/ch19-05-advanced-functions-and-closures.md +++ b/src/doc/book/src/ch19-05-advanced-functions-and-closures.md @@ -152,9 +152,9 @@ fn returns_closure() -> Box i32> { ``` This code will compile just fine. For more about trait objects, refer to the -section [“Using Trait Objects That Allow for Values of Different Types”] -[using-trait-objects-that-allow-for-values-of-different-types] -in Chapter 17. +section [“Using Trait Objects That Allow for Values of Different +Types”][using-trait-objects-that-allow-for-values-of-different-types] in Chapter 17. Next, let’s look at macros! diff --git a/src/doc/book/src/ch19-06-macros.md b/src/doc/book/src/ch19-06-macros.md index a1a23b444a..b29337e61b 100644 --- a/src/doc/book/src/ch19-06-macros.md +++ b/src/doc/book/src/ch19-06-macros.md @@ -172,8 +172,8 @@ operate on that code, and produce some code as an output rather than matching against patterns and replacing the code with other code as declarative macros do. -The three kinds of procedural macros: custom derive, attribute-like, and -function-like, all work in a similar fashion. +The three kinds of procedural macros (custom derive, attribute-like, and +function-like) all work in a similar fashion. When creating procedural macros, the definitions must reside in their own crate with a special crate type. This is for complex technical reasons that we hope @@ -353,14 +353,14 @@ pub fn hello_macro_derive(input: TokenStream) -> TokenStream { Listing 19-31: Code that most procedural macro crates will require in order to process Rust code -Notice that we’ve split the code into the `hello_macro_derive` function -responsible for parsing the `TokenStream` and the `impl_hello_macro` function -responsible for transforming the syntax tree: this makes writing a procedural -macro more convenient. The code in the outer function (`hello_macro_derive` in -this case) will be the same for almost every procedural macro crate you see or -create. The code you specify in the body of the inner function -(`impl_hello_macro` in this case) will be different depending on your -procedural macro’s purpose. +Notice that we’ve split the code into the `hello_macro_derive` function, which +is responsible for parsing the `TokenStream`, and the `impl_hello_macro` +function, which is responsible for transforming the syntax tree: this makes +writing a procedural macro more convenient. The code in the outer function +(`hello_macro_derive` in this case) will be the same for almost every +procedural macro crate you see or create. The code you specify in the body of +the inner function (`impl_hello_macro` in this case) will be different +depending on your procedural macro’s purpose. We’ve introduced three new crates: `proc_macro`, [`syn`], and [`quote`]. The `proc_macro` crate comes with Rust, so we didn’t need to add that to the @@ -498,7 +498,7 @@ and `hello_macro_derive`. Let’s hook up these crates to the code in Listing your *projects* directory using `cargo new pancakes`. We need to add `hello_macro` and `hello_macro_derive` as dependencies in the `pancakes` crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` and -`hello_macro_derive` to *https://crates.io/*, they would be regular +`hello_macro_derive` to [crates.io](https://crates.io/), they would be regular dependencies; if not, you can specify them as `path` dependencies as follows: ```toml @@ -550,14 +550,14 @@ function that generates the code you want! ### Function-like macros Function-like macros define macros that look like function calls. Similarly to -`macro_rules!` macros, they’re more flexible than functions in that they can -take an unknown number of arguments, for example. However, `macro_rules!` -macros can only be defined using the match-like syntax we discussed in the -section [“Declarative Macros with `macro_rules!` for General -Metaprogramming”][decl] earlier. Function-like macros take a `TokenStream` -parameter and their definition manipulates that `TokenStream` using Rust code -as the other two types of procedural macros do. An example of a function-like -macro is an `sql!` macro that might be called like so: +`macro_rules!` macros, they’re more flexible than functions; for example, they +can take an unknown number of arguments. However, `macro_rules!` macros can be +defined only using the match-like syntax we discussed in the section +[“Declarative Macros with `macro_rules!` for General Metaprogramming”][decl] +earlier. Function-like macros take a `TokenStream` parameter and their +definition manipulates that `TokenStream` using Rust code as the other two +types of procedural macros do. An example of a function-like macro is an `sql!` +macro that might be called like so: [decl]: #declarative-macros-with-macro_rules-for-general-metaprogramming @@ -581,10 +581,11 @@ generate. ## Summary Whew! Now you have some Rust features in your toolbox that you won’t use often, -but you’ll know they’re available in particular circumstances. We’ve introduced -several complex topics, so when you encounter them in error message suggestions -or in other peoples’ code, you’ll recognize these concepts and syntax. Use this -chapter as a reference to guide you to solutions. +but you’ll know they’re available in very particular circumstances. We’ve +introduced several complex topics so that when you encounter them in error +message suggestions or in other peoples’ code, you’ll be able to recognize +these concepts and syntax. Use this chapter as a reference to guide you to +solutions. Next, we’ll put everything we’ve discussed throughout the book into practice and do one more project! diff --git a/src/doc/book/src/ch20-00-final-project-a-web-server.md b/src/doc/book/src/ch20-00-final-project-a-web-server.md index 990337e26a..d260041e15 100644 --- a/src/doc/book/src/ch20-00-final-project-a-web-server.md +++ b/src/doc/book/src/ch20-00-final-project-a-web-server.md @@ -22,8 +22,9 @@ Here is the plan to build the web server: But before we get started, we should mention one detail: the method we’ll use won’t be the best way to build a web server with Rust. A number of -production-ready crates are available on *https://crates.io/* that provide more -complete web server and thread pool implementations than we’ll build. +production-ready crates are available on [crates.io](https://crates.io/) that +provide more complete web server and thread pool implementations than we’ll +build. However, our intention in this chapter is to help you learn, not to take the easy route. Because Rust is a systems programming language, we can choose the diff --git a/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md b/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md index f36fa026ee..61e93f1fc5 100644 --- a/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md +++ b/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md @@ -562,9 +562,9 @@ some ideas: * Add tests of the library’s functionality. * Change calls to `unwrap` to more robust error handling. * Use `ThreadPool` to perform some task other than serving web requests. -* Find a thread pool crate on *https://crates.io/* and implement a similar web - server using the crate instead. Then compare its API and robustness to the - thread pool we implemented. +* Find a thread pool crate on [crates.io](https://crates.io/) and implement a + similar web server using the crate instead. Then compare its API and + robustness to the thread pool we implemented. ## Summary diff --git a/src/doc/book/src/title-page.md b/src/doc/book/src/title-page.md index 4e77b77ebd..18a664a6b4 100644 --- a/src/doc/book/src/title-page.md +++ b/src/doc/book/src/title-page.md @@ -2,39 +2,39 @@ *by Steve Klabnik and Carol Nichols, with contributions from the Rust Community* -Welcome to The Rust Programming Language book! This version of the text assumes -you are using Rust 1.31.0 or later, with `edition="2018"` in *Cargo.toml* of +Welcome to *The Rust Programming Language* book! This version of the text assumes +you’re using Rust 1.31.0 or later with `edition="2018"` in *Cargo.toml* of all projects to use Rust 2018 Edition idioms. See the [“Installation” section of Chapter 1][install] to install or update Rust, and see the new [Appendix E][editions] for information on what editions of Rust are. -The 2018 Edition of the Rust language includes a number of improvements to make -Rust more ergonomic and easier to learn. This printing of the book has a number -of changes to reflect the improvements: +The 2018 Edition of the Rust language includes a number of improvements that +make Rust more ergonomic and easier to learn. This printing of the book +contains a number of changes to reflect those improvements: -- Chapter 7, "Managing Growing Projects with Packages, Crates, and Modules", +- Chapter 7, “Managing Growing Projects with Packages, Crates, and Modules,” has been mostly rewritten. The module system and the way paths work in the - 2018 Edition have been made more consistent. -- Chapter 10 has new sections titled "Traits as Parameters" and "Returning - Types that Implement Traits" that explain the new `impl Trait` syntax. -- Chapter 11 has a new section "Using `Result` in Tests" that shows how - to write tests that can use the `?` operator. -- The "Advanced Lifetimes" section of Chapter 19 has been removed as compiler - improvements have made the constructs in that section even more rare. -- The previous Appendix D on macros has been expanded to include procedural - macros, and has been moved to the "Macros" section in Chapter 19. -- Appendix A, "Keywords", also explains the new raw identifiers feature that - enables code written in Rust 2015 and Rust 2018 to interoperate. -- Appendix D now covers useful development tools that have been recently - released. + 2018 Edition were made more consistent. +- Chapter 10 has new sections titled “Traits as Parameters” and “Returning + Types that Implement Traits” that explain the new `impl Trait` syntax. +- Chapter 11 has a new section titled “Using `Result` in Tests” that + shows how to write tests that use the `?` operator. +- The “Advanced Lifetimes” section of Chapter 19 was removed because compiler + improvements have made the constructs in that section even rarer. +- The previous Appendix D, “Macros,” has been expanded to include procedural + macros and was moved to the “Macros” section in Chapter 19. +- Appendix A, “Keywords,” also explains the new raw identifiers feature that + enables code written in the 2015 Edition and the 2018 Edition to interoperate. +- Appendix D is now titled “Useful Development Tools” and covers recently + released tools that help you write Rust code. - We fixed a number of small errors and imprecise wording throughout the book. Thank you to the readers who reported them! Note that any code in the first printing of *The Rust Programming Language* that compiled will continue to compile without `edition="2018"` in the -project's *Cargo.toml*, even as you update the version of the Rust compiler -that you're using. That's Rust's backwards compatibility guarantees at work! +project’s *Cargo.toml*, even as you update the Rust compiler version you’re +using. That’s Rust’s backward compatibility guarantees at work! The HTML format is available online at [https://doc.rust-lang.org/stable/book/](https://doc.rust-lang.org/stable/book/) diff --git a/src/doc/book/tools/megadiff.sh b/src/doc/book/tools/megadiff.sh new file mode 100755 index 0000000000..9b0d943896 --- /dev/null +++ b/src/doc/book/tools/megadiff.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -eu + +# Remove files that are never affected by rustfmt or are otherwise uninteresting +rm -rf tmp/book-before/css/ tmp/book-before/theme/ tmp/book-before/img/ tmp/book-before/*.js \ + tmp/book-before/FontAwesome tmp/book-before/*.css tmp/book-before/*.png \ + tmp/book-before/*.json tmp/book-before/print.html + +rm -rf tmp/book-after/css/ tmp/book-after/theme/ tmp/book-after/img/ tmp/book-after/*.js \ + tmp/book-after/FontAwesome tmp/book-after/*.css tmp/book-after/*.png \ + tmp/book-after/*.json tmp/book-after/print.html + +# Get all the html files before +ls tmp/book-before/*.html | \ +# Extract just the filename so we can reuse it easily. +xargs -n 1 basename | \ +while IFS= read -r filename; do + # Remove any files that are the same before and after + diff "tmp/book-before/$filename" "tmp/book-after/$filename" > /dev/null \ + && rm "tmp/book-before/$filename" "tmp/book-after/$filename" +done diff --git a/src/doc/book/tools/src/bin/link2print.rs b/src/doc/book/tools/src/bin/link2print.rs index c2dcd56fc4..0d6d2f654a 100644 --- a/src/doc/book/tools/src/bin/link2print.rs +++ b/src/doc/book/tools/src/bin/link2print.rs @@ -54,6 +54,7 @@ fn parse_links((buffer, ref_map): (String, HashMap)) -> String { if name.starts_with("derive(") || name.starts_with("profile") || name.starts_with("test") || + name.starts_with("no_mangle") || error_code.is_match(&name) { return name } diff --git a/src/doc/book/tools/src/bin/remove_links.rs b/src/doc/book/tools/src/bin/remove_links.rs index 870088cda5..b31d7dc615 100644 --- a/src/doc/book/tools/src/bin/remove_links.rs +++ b/src/doc/book/tools/src/bin/remove_links.rs @@ -14,7 +14,7 @@ fn main () { let mut refs = HashSet::new(); // Capture all links and link references. - let regex = r"\[([^\]]+)\](?:(?:\[([^\]]+)\])|(?:\([^\)]+\)))(?i)"; + let regex = r"\[([^\]]+)\](?:(?:\[([^\]]+)\])|(?:\([^\)]+\)))(?i)"; let link_regex = Regex::new(regex).unwrap(); let first_pass = link_regex.replace_all(&buffer, |caps: &Captures<'_>| { @@ -28,7 +28,7 @@ fn main () { }); // Search for the references we need to delete. - let ref_regex = Regex::new(r"\n\[([^\]]+)\]:\s.*\n").unwrap(); + let ref_regex = Regex::new(r"(?m)^\[([^\]]+)\]:\s.*\n").unwrap(); let out = ref_regex.replace_all(&first_pass, |caps: &Captures<'_>| { let capture = caps.at(1).unwrap().to_owned(); diff --git a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md index 45b6d1024b..161b742d33 100644 --- a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md +++ b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md @@ -47,7 +47,7 @@ It's re-written our code to introduce a parameter name for that trait object. In this case, since it had no name, `cargo fix` will replace it with `_`, which is conventional for unused variables. -`cargo fix` is still pretty new, and so it can't always fix your code automatically. +`cargo fix` can't always fix your code automatically. If `cargo fix` can't fix something, it will print the warning that it cannot fix to the console. If you see one of these warnings, you'll have to update your code manually. See the corresponding section of this guide for help, and if you have diff --git a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-check-for-faster-checking.md b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-check-for-faster-checking.md index 323297d889..46166583f0 100644 --- a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-check-for-faster-checking.md +++ b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-check-for-faster-checking.md @@ -2,7 +2,7 @@ ![Minimum Rust version: 1.16](https://img.shields.io/badge/Minimum%20Rust%20Version-1.16-brightgreen.svg) -`cargo check` is a new subcommand should speed up the development +`cargo check` is a new subcommand that should speed up the development workflow in many cases. What does it do? Let's take a step back and talk about how `rustc` compiles diff --git a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-new-defaults-to-a-binary-project.md b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-new-defaults-to-a-binary-project.md index 5e12c0b052..96198aba3b 100644 --- a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-new-defaults-to-a-binary-project.md +++ b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-new-defaults-to-a-binary-project.md @@ -6,7 +6,7 @@ We try to keep Cargo’s CLI quite stable, but this change is important, and is unlikely to cause breakage. -For some background, cargo new accepts two flags: `--lib`, for creating +For some background, `cargo new` accepts two flags: `--lib`, for creating libraries, and `--bin`, for creating binaries, or executables. If you don’t pass one of these flags, it used to default to `--lib`. At the time, we made this decision because each binary (often) depends on many libraries, and so diff --git a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-rustc-for-passing-arbitrary-flags-to-rustc.md b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-rustc-for-passing-arbitrary-flags-to-rustc.md index 8a13e004fd..cd4196467f 100644 --- a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-rustc-for-passing-arbitrary-flags-to-rustc.md +++ b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-rustc-for-passing-arbitrary-flags-to-rustc.md @@ -7,7 +7,7 @@ For example, Cargo does not have a way to pass unstable flags built-in. But if we'd like to use `print-type-sizes` to see what layout information our -types have. We can run this: +types have, we can run this: ```console $ cargo rustc -- -Z print-type-sizes diff --git a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/index.md b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/index.md index 46e014500f..2608e338d6 100644 --- a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/index.md +++ b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/index.md @@ -1,6 +1,7 @@ # Cargo and crates.io [check]: cargo-check-for-faster-checking.md +[cratesio]: https://crates.io -In this chapter of the guide, we discuss a few improvements to `cargo` and crates.io. +In this chapter of the guide, we discuss a few improvements to `cargo` and [crates.io][cratesio]. A notable addition here is the new [`cargo check`][check] command. diff --git a/src/doc/edition-guide/src/rust-2018/control-flow/loops-can-break-with-a-value.md b/src/doc/edition-guide/src/rust-2018/control-flow/loops-can-break-with-a-value.md index b76a75fe75..c309998110 100644 --- a/src/doc/edition-guide/src/rust-2018/control-flow/loops-can-break-with-a-value.md +++ b/src/doc/edition-guide/src/rust-2018/control-flow/loops-can-break-with-a-value.md @@ -23,4 +23,4 @@ rather than statements. `loop` stuck out as strange in this way, as it was previously a statement. For now, this only applies to `loop`, and not things like `while` or `for`. -It's not clear yet, but we may add this to those in the future. \ No newline at end of file +See the rationale for this decision in RFC issue [#1767](https://github.com/rust-lang/rfcs/issues/1767). diff --git a/src/doc/edition-guide/src/rust-2018/data-types/inclusive-ranges.md b/src/doc/edition-guide/src/rust-2018/data-types/inclusive-ranges.md index ab27c34f40..ee460caa2e 100644 --- a/src/doc/edition-guide/src/rust-2018/data-types/inclusive-ranges.md +++ b/src/doc/edition-guide/src/rust-2018/data-types/inclusive-ranges.md @@ -3,7 +3,7 @@ ![Minimum Rust version: 1.26](https://img.shields.io/badge/Minimum%20Rust%20Version-1.26-brightgreen.svg) Since well before Rust 1.0, you’ve been able to create exclusive ranges with -.. like this: +`..` like this: ``` for i in 1..3 { diff --git a/src/doc/edition-guide/src/rust-2018/edition-changes.md b/src/doc/edition-guide/src/rust-2018/edition-changes.md index db9a54c9db..4e3288e215 100644 --- a/src/doc/edition-guide/src/rust-2018/edition-changes.md +++ b/src/doc/edition-guide/src/rust-2018/edition-changes.md @@ -3,7 +3,6 @@ The following is a summary of changes that only apply to code compiled with the 2018 edition compared to the 2015 edition. -- [At most once] `?` macro repetition operator. - [Path changes]: - Paths in `use` declarations work the same as other paths. - Paths starting with `::` must be followed with an external crate. @@ -26,8 +25,6 @@ the 2018 edition compared to the 2015 edition. specify `cargo install --path .` to install the current package. [Anonymous trait function parameters]: trait-system/no-anon-params.md -[At most once]: macros/at-most-once.md -[Non-lexical lifetimes]: ownership-and-lifetimes/non-lexical-lifetimes.md [Path changes]: module-system/path-clarity.md [Trait function parameters]: https://doc.rust-lang.org/stable/reference/items/traits.html#parameter-patterns [`dyn`]: trait-system/dyn-trait-for-trait-objects.md diff --git a/src/doc/edition-guide/src/rust-2018/macros/at-most-once.md b/src/doc/edition-guide/src/rust-2018/macros/at-most-once.md index a368cbd0e3..551934c175 100644 --- a/src/doc/edition-guide/src/rust-2018/macros/at-most-once.md +++ b/src/doc/edition-guide/src/rust-2018/macros/at-most-once.md @@ -1,6 +1,8 @@ # At most one repetition -![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg) +![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg) for 2018 edition + +![Minimum Rust version: 1.37](https://img.shields.io/badge/Minimum%20Rust%20Version-1.37-brightgreen.svg) for 2015 edition In Rust 2018, we have made a couple of changes to the macros-by-example syntax. diff --git a/src/doc/edition-guide/src/rust-2018/module-system/path-clarity.md b/src/doc/edition-guide/src/rust-2018/module-system/path-clarity.md index 37c978e00b..e4522c784f 100644 --- a/src/doc/edition-guide/src/rust-2018/module-system/path-clarity.md +++ b/src/doc/edition-guide/src/rust-2018/module-system/path-clarity.md @@ -91,6 +91,8 @@ Finally, on nightly, you'll need it for crates like: One other use for `extern crate` was to import macros; that's no longer needed. Check [the macro section](../macros/macro-changes.md) for more. +#### Renaming crates + If you've been using `as` to rename your crate like this: ```rust,ignore @@ -109,7 +111,7 @@ use self::f::Future; This change will need to happen in any module that uses `f`. -### The `crate` keyword refers to the current crate. +### The `crate` keyword refers to the current crate In `use` declarations and in other code, you can refer to the root of the current crate with the `crate::` prefix. For instance, `crate::foo::bar` will diff --git a/src/doc/edition-guide/src/rust-2018/the-compiler/incremental-compilation-for-faster-compiles.md b/src/doc/edition-guide/src/rust-2018/the-compiler/incremental-compilation-for-faster-compiles.md index 6e7ebf8a1c..8ce7a3c94f 100644 --- a/src/doc/edition-guide/src/rust-2018/the-compiler/incremental-compilation-for-faster-compiles.md +++ b/src/doc/edition-guide/src/rust-2018/the-compiler/incremental-compilation-for-faster-compiles.md @@ -12,7 +12,7 @@ compilation is that you only need to compile the code you’ve actually changed, which means that that second build is faster. This is now turned on by default. This means that your builds should be -faster! Don’t forget about cargo check when trying to get the lowest possible +faster! Don’t forget about `cargo check` when trying to get the lowest possible build times. This is still not the end story for compiler performance generally, nor diff --git a/src/doc/edition-guide/src/rust-2018/trait-system/dyn-trait-for-trait-objects.md b/src/doc/edition-guide/src/rust-2018/trait-system/dyn-trait-for-trait-objects.md index daab45beee..d6e62a262b 100644 --- a/src/doc/edition-guide/src/rust-2018/trait-system/dyn-trait-for-trait-objects.md +++ b/src/doc/edition-guide/src/rust-2018/trait-system/dyn-trait-for-trait-objects.md @@ -36,7 +36,7 @@ is sometimes slower, and often cannot be used at all when its alternatives can. Furthermore, with `impl Trait` arriving, "`impl Trait` vs `dyn Trait`" is much more symmetric, and therefore a bit nicer, than "`impl Trait` vs `Trait`". -`impl Trait` is explained [here](impl-trait-for-returning-complex-types-with-ease.md) +`impl Trait` is explained [here](impl-trait-for-returning-complex-types-with-ease.md). In the new edition, you should therefore prefer `dyn Trait` to just `Trait` where you need a trait object. \ No newline at end of file diff --git a/src/doc/edition-guide/src/rust-2018/trait-system/impl-trait-for-returning-complex-types-with-ease.md b/src/doc/edition-guide/src/rust-2018/trait-system/impl-trait-for-returning-complex-types-with-ease.md index 190b04e57f..87efbfe726 100644 --- a/src/doc/edition-guide/src/rust-2018/trait-system/impl-trait-for-returning-complex-types-with-ease.md +++ b/src/doc/edition-guide/src/rust-2018/trait-system/impl-trait-for-returning-complex-types-with-ease.md @@ -124,7 +124,7 @@ fn foo(x: T) { ``` When you call it, you set the type, `T`. "you" being the caller here. This -signature says "I accept any type that implements Trait." ("any type" == +signature says "I accept any type that implements `Trait`." ("any type" == universal in the jargon) This version: @@ -154,7 +154,7 @@ type... anyway, you can see how `F` is in the return position here. So you have the ability to choose. With `impl Trait`, you're saying "hey, some type exists that implements this -trait, but I'm not gonna tell you what it is.". So now, the caller can't +trait, but I'm not gonna tell you what it is." So now, the caller can't choose, and the function itself gets to choose. If we tried to define parse with `Result If you haven't seen the `dyn` syntax before, see the section on it. For -> versions that do not support it, replace `Rc` with `Rc`. +> If you haven't seen the `dyn` syntax before, see [the section on +> it](dyn-trait-for-trait-objects.md). For versions that do not support it, replace `Rc` +> with `Rc`. diff --git a/src/doc/embedded-book/src/start/qemu.md b/src/doc/embedded-book/src/start/qemu.md index 239ea24b32..f032a2ebac 100644 --- a/src/doc/embedded-book/src/start/qemu.md +++ b/src/doc/embedded-book/src/start/qemu.md @@ -7,6 +7,12 @@ the tooling and the development process. [LM3S6965]: http://www.ti.com/product/LM3S6965 +**IMPORTANT** +We'll use the name "app" for the project name in this tutorial. +Whenever you see the word "app" you should replace it with the name you selected +for your project. Or, you could also name your project "app" and avoid the +substitutions. + ## Creating a non standard Rust program We'll use the [`cortex-m-quickstart`] project template to generate a new @@ -14,8 +20,12 @@ project from it. [`cortex-m-quickstart`]: https://github.com/rust-embedded/cortex-m-quickstart -- Using `cargo-generate` - +### Using `cargo-generate` +First install cargo-generate +```console +cargo install cargo-generate +``` +Then generate a new project ```console cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart ``` @@ -30,7 +40,7 @@ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart cd app ``` -- Using `git` +### Using `git` Clone the repository @@ -56,12 +66,10 @@ test = false bench = false ``` -- Using neither +### Using neither Grab the latest snapshot of the `cortex-m-quickstart` template and extract it. -Using the command line: - ```console curl -LO https://github.com/rust-embedded/cortex-m-quickstart/archive/master.zip unzip master.zip @@ -75,10 +83,7 @@ download" button and then click "Download ZIP". Then fill in the placeholders in the `Cargo.toml` file as done in the second part of the "Using `git`" version. -**IMPORTANT** We'll use the name "app" for the project name in this tutorial. -Whenever you see the word "app" you should replace it with the name you selected -for your project. Or, you could also name your project "app" and avoid the -substitutions. +## Program Overview For convenience here are the most important parts of the source code in `src/main.rs`: @@ -113,19 +118,19 @@ nightly. the panicking behavior of the program. We will cover this in more detail in the [Panicking](panicking.md) chapter of the book. -[`#[entry]`] is an attribute provided by the [`cortex-m-rt`] crate that's used +[`#[entry]`][entry] is an attribute provided by the [`cortex-m-rt`] crate that's used to mark the entry point of the program. As we are not using the standard `main` interface we need another way to indicate the entry point of the program and that'd be `#[entry]`. -[`#[entry]`]: https://docs.rs/cortex-m-rt-macros/latest/cortex_m_rt_macros/attr.entry.html +[entry]: https://docs.rs/cortex-m-rt-macros/latest/cortex_m_rt_macros/attr.entry.html [`cortex-m-rt`]: https://crates.io/crates/cortex-m-rt `fn main() -> !`. Our program will be the *only* process running on the target hardware so we don't want it to end! We use a [divergent function](https://doc.rust-lang.org/rust-by-example/fn/diverging.html) (the `-> !` bit in the function signature) to ensure at compile time that'll be the case. -### Cross compiling +## Cross compiling The next step is to *cross* compile the program for the Cortex-M3 architecture. That's as simple as running `cargo build --target $TRIPLE` if you know what the @@ -154,7 +159,7 @@ cargo build --target thumbv7m-none-eabi cargo build ``` -### Inspecting +## Inspecting Now we have a non-native ELF binary in `target/thumbv7m-none-eabi/debug/app`. We can inspect it using `cargo-binutils`. @@ -293,7 +298,7 @@ HardFault: 663: ``` -### Running +## Running Next, let's see how to run an embedded program on QEMU! This time we'll use the `hello` example which actually does something. @@ -414,7 +419,7 @@ cargo run --example hello --release Hello, world! ``` -### Debugging +## Debugging Debugging is critical to embedded development. Let's see how it's done. diff --git a/src/doc/nomicon/src/README.md b/src/doc/nomicon/src/README.md index 6556a4d83f..a0bcd739e2 100644 --- a/src/doc/nomicon/src/README.md +++ b/src/doc/nomicon/src/README.md @@ -1,22 +1,14 @@ # The Rustonomicon -#### The Dark Arts of Advanced and Unsafe Rust Programming - -> Instead of the programs I had hoped for, there came only a shuddering blackness -and ineffable loneliness; and I saw at last a fearful truth which no one had -ever dared to breathe before — the unwhisperable secret of secrets — The fact -that this language of stone and stridor is not a sentient perpetuation of Rust -as London is of Old London and Paris of Old Paris, but that it is in fact -quite `unsafe`, its sprawling body imperfectly embalmed and infested with queer -animate things which have nothing to do with it as it was in compilation. - -This book digs into all the awful details that you need to understand when -writing Unsafe Rust programs. +#### The Dark Arts of Unsafe Rust > THE KNOWLEDGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF UNLEASHING INDESCRIBABLE HORRORS THAT SHATTER YOUR PSYCHE AND SET YOUR MIND ADRIFT IN THE UNKNOWABLY INFINITE COSMOS. +The Rustonomicon digs into all the awful details that you need to understand when +writing Unsafe Rust programs. + Should you wish a long and happy career of writing Rust programs, you should turn back now and forget you ever saw this book. It is not necessary. However if you intend to write unsafe code — or just want to dig into the guts of the @@ -30,12 +22,35 @@ have read it, and we will take care to occasionally give a refresher on the basics where appropriate. You can skip straight to this book if you want; just know that we won't be explaining everything from the ground up. -We're going to dig into exception-safety, pointer aliasing, memory models, -compiler and hardware implementation details, and even some type-theory. -Much text will be devoted to exotic corner cases that no one *should* ever have -to care about, but suddenly become important because we wrote `unsafe`. - -We will also be spending a lot of time talking about the different kinds of -safety and guarantees that programs could care about. +This book exists primarily as a high-level companion to [The Reference][ref]. +Where The Reference exists to detail the syntax and semantics of every part of +the language, The Rustonomicon exists to describe how to use those pieces together, +and the issues that you will have in doing so. + +The Reference will tell you the syntax and semantics of references, destructors, and +unwinding, but it won't tell you how combining them can lead to exception-safety +issues, or how to deal with those issues. + +It should be noted that when The Rustonomicon was originally written, The +Reference was in a state of complete disrepair, and so many things that should +have been covered by The Reference were originally only documented here. Since +then, The Reference has been revitalized and is properly maintained, although +it is still far from complete. In general, if the two documents disagree, The +Reference should be assumed to be correct (it isn't yet considered normative, +it's just better maintained). + +Topics that are within the scope of this book include: the meaning of (un)safety, +unsafe primitives provided by the language and standard library, techniques for +creating safe abstractions with those unsafe primitives, subtyping and variance, +exception-safety (panic/unwind-safety), working with uninitialized memory, +type punning, concurrency, interoperating with other languages (FFI), +optimization tricks, how constructs lower to compiler/OS/hardware primitives, +how to **not** make the memory model people angry, how you're **going** to make the +memory model people angry, and more. + +The Rustonomicon is not a place to exhaustively describe the semantics and guarantees +of every single API in the standard library, nor is it a place to exhaustively describe +every feature of Rust. [trpl]: ../book/index.html +[ref]: ../reference/index.html diff --git a/src/doc/reference/src/attributes/diagnostics.md b/src/doc/reference/src/attributes/diagnostics.md index 1e6f3a09c2..c648e059d5 100644 --- a/src/doc/reference/src/attributes/diagnostics.md +++ b/src/doc/reference/src/attributes/diagnostics.md @@ -188,7 +188,7 @@ five(); When used on a [trait declaration], a [call expression] of an [expression statement] to a function that returns an [impl trait] of that trait violates -the `unsued_must_use` lint. +the `unused_must_use` lint. ```rust #[must_use] diff --git a/src/doc/reference/src/conditional-compilation.md b/src/doc/reference/src/conditional-compilation.md index 4f402e3eab..911a8c330d 100644 --- a/src/doc/reference/src/conditional-compilation.md +++ b/src/doc/reference/src/conditional-compilation.md @@ -123,7 +123,6 @@ Example values: * `"android"` * `"freebsd"` * `"dragonfly"` -* `"bitrig"` * `"openbsd"` * `"netbsd"` @@ -247,8 +246,7 @@ fn needs_not_foo() { } ``` -The `cfg` attribute is allowed anywhere attributes are allowed except on -generic parameters. +The `cfg` attribute is allowed anywhere attributes are allowed. ### The `cfg_attr` attribute @@ -290,8 +288,7 @@ fn bewitched() {} > is valid. This example would be equivalent to > `#[cfg_attr(all(linux, feature ="multithreaded"), some_other_attribute)]`. -The `cfg_attr` attribute is allowed anywhere attributes are allowed except on -generic parameters. +The `cfg_attr` attribute is allowed anywhere attributes are allowed. ### The `cfg` macro diff --git a/src/doc/reference/src/const_eval.md b/src/doc/reference/src/const_eval.md index d150158885..eacd2db2c2 100644 --- a/src/doc/reference/src/const_eval.md +++ b/src/doc/reference/src/const_eval.md @@ -44,7 +44,7 @@ to be run. * [Grouped] expressions. * [Cast] expressions, except pointer to address and function pointer to address casts. -* Calls of const functions and const methods. +* Calls of [const functions] and const methods. ## Const context @@ -69,6 +69,7 @@ A _const context_ is one of the following: [cast]: expressions/operator-expr.html#type-cast-expressions [closure expressions]: expressions/closure-expr.html [comparison]: expressions/operator-expr.html#comparison-operators +[const functions]: items/functions.html#const-functions [constants]: items/constant-items.html [dereference operator]: expressions/operator-expr.html#the-dereference-operator [destructors]: destructors.html diff --git a/src/doc/reference/src/items/constant-items.md b/src/doc/reference/src/items/constant-items.md index a398fe9bf1..ab0b848309 100644 --- a/src/doc/reference/src/items/constant-items.md +++ b/src/doc/reference/src/items/constant-items.md @@ -2,10 +2,10 @@ > **Syntax**\ > _ConstantItem_ :\ ->    `const` [IDENTIFIER] `:` [_Type_] `=` [_Expression_] `;` +>    `const` ( [IDENTIFIER] | `_` ) `:` [_Type_] `=` [_Expression_] `;` -A *constant item* is a named _[constant value]_ which is not associated with a -specific memory location in the program. Constants are essentially inlined +A *constant item* is an optionally named _[constant value]_ which is not associated +with a specific memory location in the program. Constants are essentially inlined wherever they are used, meaning that they are copied directly into the relevant context when used. References to the same constant are not necessarily guaranteed to refer to the same memory address. @@ -60,8 +60,37 @@ fn create_and_drop_zero_with_destructor() { } ``` +## Unnamed constant + +Unlike an [associated] constant, a [free] constant may be unnamed by using +an underscore instead of the name. For example: + +```rust +const _: () = { struct _SameNameTwice; }; + +// OK although it is the same name as above: +const _: () = { struct _SameNameTwice; }; +``` + +As with [underscore imports], macros may safely emit the same unnamed constant in +the same scope more than once. For example, the following should not produce an error: + +```rust +macro_rules! m { + ($item: item) => { $item $item } +} + +m!(const _: () = ();); +// This expands to: +// const _: () = (); +// const _: () = (); +``` + +[associated]: glossary.html#associated-item [constant value]: const_eval.html#constant-expressions +[free]: glossary.html#free-item [static lifetime elision]: lifetime-elision.html#static-lifetime-elision [IDENTIFIER]: identifiers.html +[underscore imports]: items/use-declarations.html#underscore-imports [_Type_]: types.html#type-expressions [_Expression_]: expressions.html diff --git a/src/doc/reference/src/macros-by-example.md b/src/doc/reference/src/macros-by-example.md index c21075b4ac..37fe5e9a0b 100644 --- a/src/doc/reference/src/macros-by-example.md +++ b/src/doc/reference/src/macros-by-example.md @@ -33,8 +33,8 @@ > _MacroRepSep_ :\ >    [_Token_]_except delimiters and repetition operators_ > -> _MacroRepOp_2018+ :\ ->    `*` | `+` | `?`2018+ +> _MacroRepOp_ :\ +>    `*` | `+` | `?` > > _MacroTranscriber_ :\ >    [_DelimTokenTree_] @@ -181,10 +181,6 @@ compiler knows how to expand them properly: illegal because it does not have the same number. This requirement applies to every layer of nested repetitions. -> **Edition Differences**: The `?` repetition operator did not exist before the -> 2018 edition. Prior to the 2018 Edition, `?` was an allowed -> separator token, rather than a repetition operator. - ## Scoping, Exporting, and Importing For historical reasons, the scoping of macros by example does not work entirely like @@ -314,7 +310,7 @@ when `#[macro_use]` is applied to a module. #[macro_use(lazy_static)] // Or #[macro_use] to import all macros. extern crate lazy_static; -lazy_static!{}; +lazy_static!{} // self::lazy_static!{} // Error: lazy_static is not defined in `self` ``` diff --git a/src/doc/reference/src/procedural-macros.md b/src/doc/reference/src/procedural-macros.md index d779f4b9d6..a73d09cc05 100644 --- a/src/doc/reference/src/procedural-macros.md +++ b/src/doc/reference/src/procedural-macros.md @@ -173,7 +173,7 @@ For example, the following derive macro defines a helper attribute #[proc_macro_derive(HelperAttr, attributes(helper))] pub fn derive_helper_attr(_item: TokenStream) -> TokenStream { - TokenStream::new(); + TokenStream::new() } ``` diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md index 1962f3f97a..d75ae765cb 100644 --- a/src/doc/reference/src/tokens.md +++ b/src/doc/reference/src/tokens.md @@ -32,7 +32,7 @@ evaluated (primarily) at compile time. |----------------------------------------------|-----------------|-------------|-------------|---------------------| | [Character](#character-literals) | `'H'` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | | [String](#string-literals) | `"hello"` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | -| [Raw](#raw-string-literals) | `r#"hello"#` | 0 or more\* | All Unicode | `N/A` | +| [Raw string](#raw-string-literals) | `r#"hello"#` | 0 or more\* | All Unicode | `N/A` | | [Byte](#byte-literals) | `b'H'` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | | [Byte string](#byte-string-literals) | `b"hello"` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | | [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | 0 or more\* | All ASCII | `N/A` | @@ -88,6 +88,23 @@ evaluated (primarily) at compile time. #### Suffixes +A suffix is a non-raw identifier immediately (without whitespace) +following the primary part of a literal. + +Any kind of literal (string, integer, etc) with any suffix is valid as a token, +and can be passed to a macro without producing an error. +The macro itself will decide how to interpret such a token and whether to produce an error or not. + +```rust +macro_rules! blackhole { ($tt:tt) => () } + +blackhole!("string"suffix); // OK +``` + +However, suffixes on literal tokens parsed as Rust code are restricted. +Any suffixes are rejected on non-numeric literal tokens, +and numeric literal tokens are accepted only with suffixes from the list below. + | Integer | Floating-point | |---------|----------------| | `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `usize`, `isize` | `f32`, `f64` | diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index 84c643f965..fe611559f8 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -322,6 +322,10 @@ The `align` and `packed` modifiers cannot be applied on the same type and a `packed` type cannot transitively contain another `align`ed type. `align` and `packed` may only be applied to the [default] and [`C`] representations. +The `align` modifier can also be applied on an `enum`. +When it is, the effect on the `enum`'s alignment is the same as if the `enum` +was wrapped in a newtype `struct` with the same `align` modifier. +
***Warning:*** Dereferencing an unaligned pointer is [undefined behavior] and diff --git a/src/doc/rust-by-example/src/SUMMARY.md b/src/doc/rust-by-example/src/SUMMARY.md index 2056c4381e..7d91af4307 100644 --- a/src/doc/rust-by-example/src/SUMMARY.md +++ b/src/doc/rust-by-example/src/SUMMARY.md @@ -40,7 +40,7 @@ - [Expressions](expression.md) -- [Flow Control](flow_control.md) +- [Flow of Control](flow_control.md) - [if/else](flow_control/if_else.md) - [loop](flow_control/loop.md) - [Nesting and labels](flow_control/loop/nested.md) diff --git a/src/doc/rust-by-example/src/attribute.md b/src/doc/rust-by-example/src/attribute.md index 1b81c09976..13b0a60b46 100644 --- a/src/doc/rust-by-example/src/attribute.md +++ b/src/doc/rust-by-example/src/attribute.md @@ -33,6 +33,6 @@ Attributes can have multiple values and can be separated over multiple lines, to value4, value5)] ``` -[cfg]: attribute/cfg.html -[crate]: attribute/crate.html +[cfg]: attribute/cfg.md +[crate]: attribute/crate.md [lint]: https://en.wikipedia.org/wiki/Lint_%28software%29 diff --git a/src/doc/rust-by-example/src/attribute/cfg.md b/src/doc/rust-by-example/src/attribute/cfg.md index e7b56559f2..1b20e12f4d 100644 --- a/src/doc/rust-by-example/src/attribute/cfg.md +++ b/src/doc/rust-by-example/src/attribute/cfg.md @@ -37,5 +37,5 @@ fn main() { [the reference][ref], [`cfg!`][cfg], and [macros][macros]. [cfg]: https://doc.rust-lang.org/std/macro.cfg!.html -[macros]: macros.html +[macros]: ../macros.md [ref]: https://doc.rust-lang.org/reference/attributes.html#conditional-compilation diff --git a/src/doc/rust-by-example/src/compatibility.md b/src/doc/rust-by-example/src/compatibility.md index c756e25d71..00424ceb22 100644 --- a/src/doc/rust-by-example/src/compatibility.md +++ b/src/doc/rust-by-example/src/compatibility.md @@ -4,4 +4,4 @@ The Rust language is fastly evolving, and because of this certain compatibility issues can arise, despite efforts to ensure forwards-compatibility wherever possible. -* [Raw identifiers](compatibility/raw_identifiers.html) +* [Raw identifiers](compatibility/raw_identifiers.md) diff --git a/src/doc/rust-by-example/src/conversion.md b/src/doc/rust-by-example/src/conversion.md index f7f950ce32..78d9e2d31e 100644 --- a/src/doc/rust-by-example/src/conversion.md +++ b/src/doc/rust-by-example/src/conversion.md @@ -5,6 +5,6 @@ conversions will use the [`From`] and [`Into`] traits. However there are more specific ones for the more common cases, in particular when converting to and from `String`s. -[traits]: trait.html +[traits]: trait.md [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html diff --git a/src/doc/rust-by-example/src/conversion/string.md b/src/doc/rust-by-example/src/conversion/string.md index 14c413a2ba..2bec02f6df 100644 --- a/src/doc/rust-by-example/src/conversion/string.md +++ b/src/doc/rust-by-example/src/conversion/string.md @@ -50,6 +50,6 @@ fn main() { [`ToString`]: https://doc.rust-lang.org/std/string/trait.ToString.html [Display]: https://doc.rust-lang.org/std/fmt/trait.Display.html -[print]: hello/print.html +[print]: ../hello/print.md [`parse`]: https://doc.rust-lang.org/std/primitive.str.html#method.parse [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html diff --git a/src/doc/rust-by-example/src/crates/lib.md b/src/doc/rust-by-example/src/crates/lib.md index 24a51b1b2a..f20fe5990e 100644 --- a/src/doc/rust-by-example/src/crates/lib.md +++ b/src/doc/rust-by-example/src/crates/lib.md @@ -28,4 +28,4 @@ Libraries get prefixed with "lib", and by default they get named after their crate file, but this default name can be overridden using the [`crate_name` attribute][crate-name]. -[crate-name]: attribute/crate.html \ No newline at end of file +[crate-name]: ../attribute/crate.md \ No newline at end of file diff --git a/src/doc/rust-by-example/src/custom_types/constants.md b/src/doc/rust-by-example/src/custom_types/constants.md index 5fb868b9b5..8878ba834e 100644 --- a/src/doc/rust-by-example/src/custom_types/constants.md +++ b/src/doc/rust-by-example/src/custom_types/constants.md @@ -38,5 +38,5 @@ fn main() { https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md), [`'static` lifetime][static] -[static]: scope/lifetime/static_lifetime.html -[unsafe]: unsafe.html +[static]: ../scope/lifetime/static_lifetime.md +[unsafe]: ../unsafe.md diff --git a/src/doc/rust-by-example/src/custom_types/enum.md b/src/doc/rust-by-example/src/custom_types/enum.md index 6756789dd4..5eae819adc 100644 --- a/src/doc/rust-by-example/src/custom_types/enum.md +++ b/src/doc/rust-by-example/src/custom_types/enum.md @@ -16,7 +16,7 @@ enum WebEvent { // like tuple structs, KeyPress(char), Paste(String), - // or like structures. + // or c-like structures. Click { x: i64, y: i64 }, } @@ -58,6 +58,6 @@ fn main() { [`match`][match], [`fn`][fn], and [`String`][str] [c_struct]: https://en.wikipedia.org/wiki/Struct_(C_programming_language) -[match]: flow_control/match.html -[fn]: fn.html -[str]: std/str.html +[match]: ../flow_control/match.md +[fn]: ../fn.md +[str]: ../std/str.md diff --git a/src/doc/rust-by-example/src/custom_types/enum/c_like.md b/src/doc/rust-by-example/src/custom_types/enum/c_like.md index 9dbc37c270..65f832bef8 100644 --- a/src/doc/rust-by-example/src/custom_types/enum/c_like.md +++ b/src/doc/rust-by-example/src/custom_types/enum/c_like.md @@ -34,4 +34,4 @@ fn main() { [casting][cast] -[cast]: types/cast.html +[cast]: ../../types/cast.md diff --git a/src/doc/rust-by-example/src/custom_types/enum/enum_use.md b/src/doc/rust-by-example/src/custom_types/enum/enum_use.md index a6ac21a9b2..cf75c67ba4 100644 --- a/src/doc/rust-by-example/src/custom_types/enum/enum_use.md +++ b/src/doc/rust-by-example/src/custom_types/enum/enum_use.md @@ -46,5 +46,5 @@ fn main() { [`match`][match] and [`use`][use] -[use]: mod/use.html -[match]: flow_control/match.html +[use]: ../../mod/use.md +[match]: ../../flow_control/match.md diff --git a/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md b/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md index 61109d1596..84855d1c54 100644 --- a/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md +++ b/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md @@ -75,5 +75,5 @@ fn main() { [`Box`][box] and [methods][methods] -[box]: std/box.html -[methods]: fn/methods.html +[box]: ../../std/box.md +[methods]: ../../fn/methods.md diff --git a/src/doc/rust-by-example/src/custom_types/structs.md b/src/doc/rust-by-example/src/custom_types/structs.md index f51d67a74d..0b620bf38a 100644 --- a/src/doc/rust-by-example/src/custom_types/structs.md +++ b/src/doc/rust-by-example/src/custom_types/structs.md @@ -89,6 +89,6 @@ fn main() { [`attributes`][attributes] and [destructuring][destructuring] -[attributes]: attribute.html +[attributes]: ../attribute.md [c_struct]: https://en.wikipedia.org/wiki/Struct_(C_programming_language) -[destructuring]: flow_control/match/destructuring.html +[destructuring]: ../flow_control/match/destructuring.md diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md b/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md index 331b458189..793673f8df 100644 --- a/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md +++ b/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md @@ -55,4 +55,4 @@ fn main() { } ``` -[enter_question_mark]: error/result/enter_question_mark.html +[enter_question_mark]: ../result/enter_question_mark.md diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md index 74bcddcca1..bf93e8a42d 100644 --- a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md +++ b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md @@ -25,7 +25,6 @@ Here, we rewrite the previous example using `?`. As a result, the ```rust,editable use std::error; use std::fmt; -use std::num::ParseIntError; // Change the alias to `Box`. type Result = std::result::Result>; diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/wrap_error.md b/src/doc/rust-by-example/src/error/multiple_error_types/wrap_error.md index f384c0c247..e8acd25197 100644 --- a/src/doc/rust-by-example/src/error/multiple_error_types/wrap_error.md +++ b/src/doc/rust-by-example/src/error/multiple_error_types/wrap_error.md @@ -83,4 +83,4 @@ for you. [`From::from`][from] and [`Enums`][enums] [from]: https://doc.rust-lang.org/std/convert/trait.From.html -[enums]: custom_types/enum.html +[enums]: ../../custom_types/enum.md diff --git a/src/doc/rust-by-example/src/error/option_unwrap/and_then.md b/src/doc/rust-by-example/src/error/option_unwrap/and_then.md index 99d8133ac6..c065f2043e 100644 --- a/src/doc/rust-by-example/src/error/option_unwrap/and_then.md +++ b/src/doc/rust-by-example/src/error/option_unwrap/and_then.md @@ -71,6 +71,6 @@ fn main() { [closures][closures], [`Option`][option], and [`Option::and_then()`][and_then] -[closures]: fn/closures.html +[closures]: ../../fn/closures.md [option]: https://doc.rust-lang.org/std/option/enum.Option.html [and_then]: https://doc.rust-lang.org/std/option/enum.Option.html#method.and_then diff --git a/src/doc/rust-by-example/src/error/option_unwrap/map.md b/src/doc/rust-by-example/src/error/option_unwrap/map.md index 89b06cca90..c458e7d955 100644 --- a/src/doc/rust-by-example/src/error/option_unwrap/map.md +++ b/src/doc/rust-by-example/src/error/option_unwrap/map.md @@ -81,6 +81,6 @@ fn main() { [closures][closures], [`Option`][option], [`Option::map()`][map] [combinators]: https://doc.rust-lang.org/book/glossary.html#combinators -[closures]: fn/closures.html +[closures]: ../../fn/closures.md [option]: https://doc.rust-lang.org/std/option/enum.Option.html [map]: https://doc.rust-lang.org/std/option/enum.Option.html#method.map diff --git a/src/doc/rust-by-example/src/error/result.md b/src/doc/rust-by-example/src/error/result.md index 1dede872e8..3202b314ea 100644 --- a/src/doc/rust-by-example/src/error/result.md +++ b/src/doc/rust-by-example/src/error/result.md @@ -80,4 +80,4 @@ fn main() -> Result<(), ParseIntError> { [result]: https://doc.rust-lang.org/std/result/enum.Result.html [parse]: https://doc.rust-lang.org/std/primitive.str.html#method.parse [`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html -[the following section]: error/result/early_returns.html +[the following section]: result/early_returns.md diff --git a/src/doc/rust-by-example/src/error/result/enter_question_mark.md b/src/doc/rust-by-example/src/error/result/enter_question_mark.md index aa4627c2c3..5fb9ccfb02 100644 --- a/src/doc/rust-by-example/src/error/result/enter_question_mark.md +++ b/src/doc/rust-by-example/src/error/result/enter_question_mark.md @@ -44,6 +44,9 @@ at older code. The same `multiply` function from the previous example would look like this using `try!`: ```rust,editable +// To compile and run this example without errors, while using Cargo, change the value +// of the `edition` field, in the `[package]` section of the `Cargo.toml` file, to "2015". + use std::num::ParseIntError; fn multiply(first_number_str: &str, second_number_str: &str) -> Result { @@ -69,4 +72,4 @@ fn main() { [^†]: See [re-enter ?][re_enter_?] for more details. -[re_enter_?]: error/multiple_error_types/reenter_question_mark.html +[re_enter_?]: ../multiple_error_types/reenter_question_mark.md diff --git a/src/doc/rust-by-example/src/error/result/result_alias.md b/src/doc/rust-by-example/src/error/result/result_alias.md index c0466357b1..c4073980fc 100644 --- a/src/doc/rust-by-example/src/error/result/result_alias.md +++ b/src/doc/rust-by-example/src/error/result/result_alias.md @@ -42,5 +42,5 @@ fn main() { [`io::Result`][io_result] -[typealias]: types/alias.html +[typealias]: ../../types/alias.md [io_result]: https://doc.rust-lang.org/std/io/type.Result.html diff --git a/src/doc/rust-by-example/src/flow_control.md b/src/doc/rust-by-example/src/flow_control.md index 4cd6d0d8e7..c8a2f9ed87 100644 --- a/src/doc/rust-by-example/src/flow_control.md +++ b/src/doc/rust-by-example/src/flow_control.md @@ -1,4 +1,4 @@ -# Flow Control +# Flow of Control An essential part of any programming languages are ways to modify control flow: `if`/`else`, `for`, and others. Let's talk about them in Rust. diff --git a/src/doc/rust-by-example/src/flow_control/for.md b/src/doc/rust-by-example/src/flow_control/for.md index a24228e8f2..a8a4762a2d 100644 --- a/src/doc/rust-by-example/src/flow_control/for.md +++ b/src/doc/rust-by-example/src/flow_control/for.md @@ -117,4 +117,4 @@ implies differing actions that are able to be performed. [Iterator][iter] -[iter]: trait/iter.html +[iter]: ../trait/iter.md diff --git a/src/doc/rust-by-example/src/flow_control/if_let.md b/src/doc/rust-by-example/src/flow_control/if_let.md index ffbf0da989..bcdebcedbd 100644 --- a/src/doc/rust-by-example/src/flow_control/if_let.md +++ b/src/doc/rust-by-example/src/flow_control/if_let.md @@ -118,6 +118,6 @@ fn main() { [`enum`][enum], [`Option`][option], and the [RFC][if_let_rfc] -[enum]: custom_types/enum.html +[enum]: ../custom_types/enum.md [if_let_rfc]: https://github.com/rust-lang/rfcs/pull/160 -[option]: std/option.html +[option]: ../std/option.md diff --git a/src/doc/rust-by-example/src/flow_control/match/binding.md b/src/doc/rust-by-example/src/flow_control/match/binding.md index 9a22503207..385035dc15 100644 --- a/src/doc/rust-by-example/src/flow_control/match/binding.md +++ b/src/doc/rust-by-example/src/flow_control/match/binding.md @@ -29,4 +29,4 @@ fn main() { ### See also: [functions] -[functions]: fn.html +[functions]: ../../fn.md diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring.md b/src/doc/rust-by-example/src/flow_control/match/destructuring.md index ce59b15407..9f9a73e025 100644 --- a/src/doc/rust-by-example/src/flow_control/match/destructuring.md +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring.md @@ -8,7 +8,7 @@ A `match` block can destructure items in a variety of ways. * [Destructuring Tuples][tuple] -[enum]: flow_control/match/destructuring/destructure_enum.html -[refs]: flow_control/match/destructuring/destructure_pointers.html -[struct]: flow_control/match/destructuring/destructure_structures.html -[tuple]: flow_control/match/destructuring/destructure_tuple.html +[enum]: destructuring/destructure_enum.md +[refs]: destructuring/destructure_pointers.md +[struct]: destructuring/destructure_structures.md +[tuple]: destructuring/destructure_tuple.md diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_enum.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_enum.md index a5022330ba..60d8969459 100644 --- a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_enum.md +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_enum.md @@ -49,6 +49,6 @@ fn main() { [`#[allow(...)]`][allow], [color models][color_models] and [`enum`][enum] -[allow]: attribute/unused.html +[allow]: ../../../attribute/unused.md [color_models]: https://en.wikipedia.org/wiki/Color_model -[enum]: custom_types/enum.html +[enum]: ../../../custom_types/enum.md diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md index bf35ab1897..35ce28db87 100644 --- a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md @@ -29,4 +29,4 @@ fn main() { ### See also: -[Structs](custom_types/structs.html), [The ref pattern](scope/borrow/ref.html) +[Structs](../../../custom_types/structs.md), [The ref pattern](../../../scope/borrow/ref.md) diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md index c7e1024aca..9d6260e433 100644 --- a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md @@ -21,4 +21,4 @@ fn main() { ### See also: -[Tuples](primitives/tuples.html) +[Tuples](../../../primitives/tuples.md) diff --git a/src/doc/rust-by-example/src/flow_control/match/guard.md b/src/doc/rust-by-example/src/flow_control/match/guard.md index e52c198e8f..336b7f1233 100644 --- a/src/doc/rust-by-example/src/flow_control/match/guard.md +++ b/src/doc/rust-by-example/src/flow_control/match/guard.md @@ -20,4 +20,4 @@ fn main() { ### See also: -[Tuples](primitives/tuples.html) +[Tuples](../../primitives/tuples.md) diff --git a/src/doc/rust-by-example/src/flow_control/while_let.md b/src/doc/rust-by-example/src/flow_control/while_let.md index 5938de4ee4..897375a8e2 100644 --- a/src/doc/rust-by-example/src/flow_control/while_let.md +++ b/src/doc/rust-by-example/src/flow_control/while_let.md @@ -57,6 +57,6 @@ fn main() { [`enum`][enum], [`Option`][option], and the [RFC][while_let_rfc] -[enum]: custom_types/enum.html -[option]: std/option.html +[enum]: ../custom_types/enum.md +[option]: ../std/option.md [while_let_rfc]: https://github.com/rust-lang/rfcs/pull/214 diff --git a/src/doc/rust-by-example/src/fn/closures/anonymity.md b/src/doc/rust-by-example/src/fn/closures/anonymity.md index 5e6840c9b4..7008a446b8 100644 --- a/src/doc/rust-by-example/src/fn/closures/anonymity.md +++ b/src/doc/rust-by-example/src/fn/closures/anonymity.md @@ -49,7 +49,7 @@ fn main() { [A thorough analysis][thorough_analysis], [`Fn`][fn], [`FnMut`][fn_mut], and [`FnOnce`][fn_once] -[generics]: generics.html +[generics]: ../../generics.md [fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html [fn_mut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html [fn_once]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html diff --git a/src/doc/rust-by-example/src/fn/closures/capture.md b/src/doc/rust-by-example/src/fn/closures/capture.md index 00f500b591..36468782f3 100644 --- a/src/doc/rust-by-example/src/fn/closures/capture.md +++ b/src/doc/rust-by-example/src/fn/closures/capture.md @@ -97,5 +97,5 @@ fn main() { [`Box`][box] and [`std::mem::drop`][drop] -[box]: std/box.html +[box]: ../../std/box.md [drop]: https://doc.rust-lang.org/std/mem/fn.drop.html diff --git a/src/doc/rust-by-example/src/fn/closures/output_parameters.md b/src/doc/rust-by-example/src/fn/closures/output_parameters.md index 87fe26f6f3..0810b281ac 100644 --- a/src/doc/rust-by-example/src/fn/closures/output_parameters.md +++ b/src/doc/rust-by-example/src/fn/closures/output_parameters.md @@ -46,8 +46,8 @@ fn main() { [Boxing][box], [`Fn`][fn], [`FnMut`][fnmut], and [Generics][generics]. -[box]: std/box.html +[box]: ../../std/box.md [fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html [fnmut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html [fnbox]: https://doc.rust-lang.org/std/boxed/trait.FnBox.html -[generics]: generics.html +[generics]: ../../generics.md diff --git a/src/doc/rust-by-example/src/fn/diverging.md b/src/doc/rust-by-example/src/fn/diverging.md index 6cd63a0d36..19cf27c080 100644 --- a/src/doc/rust-by-example/src/fn/diverging.md +++ b/src/doc/rust-by-example/src/fn/diverging.md @@ -9,7 +9,7 @@ fn foo() -> ! { ``` As opposed to all the other types, this one cannot be instantiated, because the -set of all possible values this type can have is empty. Note, that it is +set of all possible values this type can have is empty. Note that, it is different from the `()` type, which has exactly one possible value. For example, this function returns as usual, although there is no information diff --git a/src/doc/rust-by-example/src/generics.md b/src/doc/rust-by-example/src/generics.md index 641e0cf0ae..d1ecca5574 100644 --- a/src/doc/rust-by-example/src/generics.md +++ b/src/doc/rust-by-example/src/generics.md @@ -60,5 +60,5 @@ fn main() { [`struct`s][structs] -[structs]: custom_types/structs.html +[structs]: custom_types/structs.md [camelcase]: https://en.wikipedia.org/wiki/CamelCase diff --git a/src/doc/rust-by-example/src/generics/assoc_items/the_problem.md b/src/doc/rust-by-example/src/generics/assoc_items/the_problem.md index dca8f9b33f..bc6f7636b1 100644 --- a/src/doc/rust-by-example/src/generics/assoc_items/the_problem.md +++ b/src/doc/rust-by-example/src/generics/assoc_items/the_problem.md @@ -63,5 +63,5 @@ fn main() { [`struct`s][structs], and [`trait`s][traits] -[structs]: custom_types/structs.html -[traits]: trait.html +[structs]: ../../custom_types/structs.md +[traits]: ../../trait.md diff --git a/src/doc/rust-by-example/src/generics/assoc_items/types.md b/src/doc/rust-by-example/src/generics/assoc_items/types.md index 25196f2e0e..0358fcebca 100644 --- a/src/doc/rust-by-example/src/generics/assoc_items/types.md +++ b/src/doc/rust-by-example/src/generics/assoc_items/types.md @@ -41,7 +41,7 @@ trait Contains { type A; type B; - fn contains(&self, &Self::A, &Self::B) -> bool; + fn contains(&self, _: &Self::A, _: &Self::B) -> bool; fn first(&self) -> i32; fn last(&self) -> i32; } diff --git a/src/doc/rust-by-example/src/generics/bounds.md b/src/doc/rust-by-example/src/generics/bounds.md index ca9496013c..86e54e670c 100644 --- a/src/doc/rust-by-example/src/generics/bounds.md +++ b/src/doc/rust-by-example/src/generics/bounds.md @@ -74,8 +74,8 @@ some cases to be more expressive. [`std::fmt`][fmt], [`struct`s][structs], and [`trait`s][traits] -[fmt]: hello/print.html -[methods]: fn/methods.html -[structs]: custom_types/structs.html -[traits]: trait.html -[where]: generics/where.html +[fmt]: ../hello/print.md +[methods]: ../fn/methods.md +[structs]: ../custom_types/structs.md +[traits]: ../trait.md +[where]: ../generics/where.md diff --git a/src/doc/rust-by-example/src/generics/bounds/testcase_empty.md b/src/doc/rust-by-example/src/generics/bounds/testcase_empty.md index 9e0a850af8..df4904a3d5 100644 --- a/src/doc/rust-by-example/src/generics/bounds/testcase_empty.md +++ b/src/doc/rust-by-example/src/generics/bounds/testcase_empty.md @@ -40,4 +40,4 @@ fn main() { [eq]: https://doc.rust-lang.org/std/cmp/trait.Eq.html [ord]: https://doc.rust-lang.org/std/cmp/trait.Ord.html -[traits]: trait.html +[traits]: ../../trait.md diff --git a/src/doc/rust-by-example/src/generics/gen_fn.md b/src/doc/rust-by-example/src/generics/gen_fn.md index 3c8b2f9528..264057687d 100644 --- a/src/doc/rust-by-example/src/generics/gen_fn.md +++ b/src/doc/rust-by-example/src/generics/gen_fn.md @@ -55,5 +55,5 @@ fn main() { [functions][fn] and [`struct`s][structs] -[fn]: fn.html -[structs]: custom_types/structs.html +[fn]: ../fn.md +[structs]: ../custom_types/structs.md diff --git a/src/doc/rust-by-example/src/generics/gen_trait.md b/src/doc/rust-by-example/src/generics/gen_trait.md index adde475b42..6847dfea81 100644 --- a/src/doc/rust-by-example/src/generics/gen_trait.md +++ b/src/doc/rust-by-example/src/generics/gen_trait.md @@ -41,5 +41,5 @@ fn main() { [`Drop`][Drop], [`struct`][structs], and [`trait`][traits] [Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html -[structs]: custom_types/structs.html -[traits]: trait.html +[structs]: ../custom_types/structs.md +[traits]: ../trait.md diff --git a/src/doc/rust-by-example/src/generics/impl.md b/src/doc/rust-by-example/src/generics/impl.md index f5b4c44fd9..6410739a67 100644 --- a/src/doc/rust-by-example/src/generics/impl.md +++ b/src/doc/rust-by-example/src/generics/impl.md @@ -46,7 +46,7 @@ fn main() { [functions returning references][fn], [`impl`][methods], and [`struct`][structs] -[fn]: scope/lifetime/fn.html -[methods]: fn/methods.html +[fn]: ../scope/lifetime/fn.md +[methods]: ../fn/methods.md [specialization_plans]: https://blog.rust-lang.org/2015/05/11/traits.html#the-future -[structs]: custom_types/structs.html +[structs]: ../custom_types/structs.md diff --git a/src/doc/rust-by-example/src/generics/multi_bounds.md b/src/doc/rust-by-example/src/generics/multi_bounds.md index c563282bcb..5f51a6c24b 100644 --- a/src/doc/rust-by-example/src/generics/multi_bounds.md +++ b/src/doc/rust-by-example/src/generics/multi_bounds.md @@ -33,5 +33,5 @@ fn main() { [`std::fmt`][fmt] and [`trait`s][traits] -[fmt]: hello/print.html -[traits]: trait.html +[fmt]: ../hello/print.md +[traits]: ../trait.md diff --git a/src/doc/rust-by-example/src/generics/new_types.md b/src/doc/rust-by-example/src/generics/new_types.md index a77282ef8a..ccbbbb03cf 100644 --- a/src/doc/rust-by-example/src/generics/new_types.md +++ b/src/doc/rust-by-example/src/generics/new_types.md @@ -54,5 +54,5 @@ fn main() { [`structs`][struct] -[struct]: custom_types/structs.html +[struct]: ../custom_types/structs.md diff --git a/src/doc/rust-by-example/src/generics/phantom.md b/src/doc/rust-by-example/src/generics/phantom.md index 7e9d7f5f04..59cf125d11 100644 --- a/src/doc/rust-by-example/src/generics/phantom.md +++ b/src/doc/rust-by-example/src/generics/phantom.md @@ -57,7 +57,7 @@ fn main() { [Derive], [struct], and [TupleStructs] -[Derive]: trait/derive.html -[struct]: custom_types/structs.html -[TupleStructs]: custom_types/structs.html +[Derive]: ../trait/derive.md +[struct]: ../custom_types/structs.md +[TupleStructs]: ../custom_types/structs.md [std::marker::PhantomData]: https://doc.rust-lang.org/std/marker/struct.PhantomData.html \ No newline at end of file diff --git a/src/doc/rust-by-example/src/generics/phantom/testcase_units.md b/src/doc/rust-by-example/src/generics/phantom/testcase_units.md index 52480316f7..00f59fe2de 100644 --- a/src/doc/rust-by-example/src/generics/phantom/testcase_units.md +++ b/src/doc/rust-by-example/src/generics/phantom/testcase_units.md @@ -77,12 +77,12 @@ fn main() { [Borrowing (`&`)], [Bounds (`X: Y`)], [enum], [impl & self], [Overloading], [ref], [Traits (`X for Y`)], and [TupleStructs]. -[Borrowing (`&`)]: scope/borrow.html -[Bounds (`X: Y`)]: generics/bounds.html -[enum]: custom_types/enum.html -[impl & self]: fn/methods.html -[Overloading]: trait/ops.html -[ref]: scope/borrow/ref.html -[Traits (`X for Y`)]: trait.html -[TupleStructs]: custom_types/structs.html +[Borrowing (`&`)]: ../../scope/borrow.md +[Bounds (`X: Y`)]: ../../generics/bounds.md +[enum]: ../../custom_types/enum.md +[impl & self]: ../../fn/methods.md +[Overloading]: ../../trait/ops.md +[ref]: ../../scope/borrow/ref.md +[Traits (`X for Y`)]: ../../trait.md +[TupleStructs]: ../../custom_types/structs.md [std::marker::PhantomData]: https://doc.rust-lang.org/std/marker/struct.PhantomData.html diff --git a/src/doc/rust-by-example/src/generics/where.md b/src/doc/rust-by-example/src/generics/where.md index 89da6de87c..f35f03f928 100644 --- a/src/doc/rust-by-example/src/generics/where.md +++ b/src/doc/rust-by-example/src/generics/where.md @@ -50,6 +50,6 @@ fn main() { [RFC][where], [`struct`][struct], and [`trait`][trait] -[struct]: custom_types/structs.html -[trait]: trait.html +[struct]: ../custom_types/structs.md +[trait]: ../trait.md [where]: https://github.com/rust-lang/rfcs/blob/master/text/0135-where.md diff --git a/src/doc/rust-by-example/src/hello.md b/src/doc/rust-by-example/src/hello.md index a11e309a06..2a8d3153f3 100644 --- a/src/doc/rust-by-example/src/hello.md +++ b/src/doc/rust-by-example/src/hello.md @@ -3,16 +3,16 @@ This is the source code of the traditional Hello World program. ```rust,editable -// This is a comment, and will be ignored by the compiler +// This is a comment, and is ignored by the compiler // You can test this code by clicking the "Run" button over there -> -// or if prefer to use your keyboard, you can use the "Ctrl + Enter" shortcut +// or if you prefer to use your keyboard, you can use the "Ctrl + Enter" shortcut // This code is editable, feel free to hack it! // You can always return to the original code by clicking the "Reset" button -> // This is the main function fn main() { - // The statements here will be executed when the compiled binary is called + // Statements here are executed when the compiled binary is called // Print text to the console println!("Hello World!"); @@ -46,4 +46,4 @@ Hello World! I'm a Rustacean! ``` -[macros]: macros.html +[macros]: macros.md diff --git a/src/doc/rust-by-example/src/hello/comment.md b/src/doc/rust-by-example/src/hello/comment.md index 951b7df858..8cd1ccf553 100644 --- a/src/doc/rust-by-example/src/hello/comment.md +++ b/src/doc/rust-by-example/src/hello/comment.md @@ -1,43 +1,43 @@ # Comments -Any program requires comments and indeed Rust supports +Any program requires comments, and Rust supports a few different varieties: * *Regular comments* which are ignored by the compiler: - - `// Line comments which go to the end of the line.` - - `/* Block comments which go to the closing delimiter. */` + * `// Line comments which go to the end of the line.` + * `/* Block comments which go to the closing delimiter. */` * *Doc comments* which are parsed into HTML library -[documentation][docs]: - - `/// Generate library docs for the following item.` - - `//! Generate library docs for the enclosing item.` + [documentation][docs]: + * `/// Generate library docs for the following item.` + * `//! Generate library docs for the enclosing item.` ```rust,editable fn main() { // This is an example of a line comment - // Notice how there are two slashes at the beginning of the line - // And that nothing written inside these will be read by the compiler + // There are two slashes at the beginning of the line + // And nothing written inside these will be read by the compiler // println!("Hello, world!"); // Run it. See? Now try deleting the two slashes, and run it again. /* - * This is another type of comment, the block comment. In general, - * the line comment is the recommended comment style however the - * block comment is extremely useful for temporarily disabling - * a large chunk of code. /* Block comments can be /* nested, */ */ - * so it takes only a few keystrokes to comment out all the lines + * This is another type of comment, a block comment. In general, + * line comments are the recommended comment style. But + * block comments are extremely useful for temporarily disabling + * chunks of code. /* Block comments can be /* nested, */ */ + * so it takes only a few keystrokes to comment out everything * in this main() function. /*/*/* Try it yourself! */*/*/ */ /* - Note, the previous column of `*` was entirely for style. There's + Note: The previous column of `*` was entirely for style. There's no actual need for it. */ - // Observe how block comments allow easy expression manipulation - // which line comments do not. Deleting the comment delimiters - // will change the result: + // You can manipulate expressions more easily with block comments + // than with line comments. Try deleting the comment delimiters + // to change the result: let x = 5 + /* 90 + */ 5; println!("Is `x` 10 or 100? x = {}", x); } @@ -48,4 +48,4 @@ fn main() { [Library documentation][docs] -[docs]: meta/doc.html +[docs]: ../meta/doc.md diff --git a/src/doc/rust-by-example/src/hello/print.md b/src/doc/rust-by-example/src/hello/print.md index 2ae8c80440..495f3f2061 100644 --- a/src/doc/rust-by-example/src/hello/print.md +++ b/src/doc/rust-by-example/src/hello/print.md @@ -9,8 +9,8 @@ some of which include: * `eprint!`: same as `format!` but the text is printed to the standard error (io::stderr). * `eprintln!`: same as `eprint!`but a newline is appended. -All parse text in the same fashion. A plus is that the formatting correctness will -be checked at compile time. +All parse text in the same fashion. As a plus, Rust checks formatting +correctness at compile time. ```rust,editable,ignore,mdbook-runnable fn main() { @@ -18,8 +18,8 @@ fn main() { // arguments. These will be stringified. println!("{} days", 31); - // Without a suffix, 31 becomes an i32. You can change what type 31 is, - // with a suffix. + // Without a suffix, 31 becomes an i32. You can change what type 31 is + // by providing a suffix. // There are various optional patterns this works with. Positional // arguments can be used. @@ -41,12 +41,12 @@ fn main() { // You can pad numbers with extra zeroes. This will output "000001". println!("{number:>0width$}", number=1, width=6); - // It will even check to make sure the correct number of arguments are + // Rust even checks to make sure the correct number of arguments are // used. println!("My name is {0}, {1} {0}", "Bond"); // FIXME ^ Add the missing argument: "James" - // Create a structure which contains an `i32`. Name it `Structure`. + // Create a structure named `Structure` which contains an `i32`. #[allow(dead_code)] struct Structure(i32); @@ -64,7 +64,7 @@ of text. The base form of two important ones are listed below: * `fmt::Display`: Uses the `{}` marker. Format text in a more elegant, user friendly fashion. -Here, `fmt::Display` was used because the std library provides implementations +Here, we used `fmt::Display `because the std library provides implementations for these types. To print text for custom types, more steps are required. Implementing the `fmt::Display` trait automagically implements the @@ -76,7 +76,7 @@ Implementing the `fmt::Display` trait automagically implements the error. * Add a `println!` macro that prints: `Pi is roughly 3.142` by controlling the number of decimal places shown. For the purposes of this exercise, - use `let pi = 3.141592` as an estimate for Pi. (Hint: you may need to + use `let pi = 3.141592` as an estimate for pi. (Hint: you may need to check the [`std::fmt`][fmt] documentation for setting the number of decimals to display) @@ -86,9 +86,9 @@ Implementing the `fmt::Display` trait automagically implements the and [`traits`][traits] [fmt]: https://doc.rust-lang.org/std/fmt/ -[macros]: macros.html -[string]: std/str.html -[structs]: custom_types/structs.html -[traits]: trait.html +[macros]: ../macros.md +[string]: ../std/str.md +[structs]: ../custom_types/structs.md +[traits]: ../trait.md [`ToString`]: https://doc.rust-lang.org/std/string/trait.ToString.html -[convert]: conversion/string.html +[convert]: ../conversion/string.md diff --git a/src/doc/rust-by-example/src/hello/print/fmt.md b/src/doc/rust-by-example/src/hello/print/fmt.md index 4059c97f38..5cdcda89f0 100644 --- a/src/doc/rust-by-example/src/hello/print/fmt.md +++ b/src/doc/rust-by-example/src/hello/print/fmt.md @@ -26,7 +26,7 @@ struct City { } impl Display for City { - // `f` is a buffer, this method must write the formatted string into it + // `f` is a buffer, and this method must write the formatted string into it fn fmt(&self, f: &mut Formatter) -> fmt::Result { let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' }; let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' }; @@ -59,7 +59,7 @@ fn main() { Color { red: 0, green: 0, blue: 0 }, ].iter() { // Switch this to use {} once you've added an implementation - // for fmt::Display + // for fmt::Display. println!("{:?}", *color); } } diff --git a/src/doc/rust-by-example/src/hello/print/print_debug.md b/src/doc/rust-by-example/src/hello/print/print_debug.md index 4e68b7fadc..05df667f0d 100644 --- a/src/doc/rust-by-example/src/hello/print/print_debug.md +++ b/src/doc/rust-by-example/src/hello/print/print_debug.md @@ -11,7 +11,7 @@ not true for `fmt::Display` which must be manually implemented. ```rust // This structure cannot be printed either with `fmt::Display` or -// with `fmt::Debug` +// with `fmt::Debug`. struct UnPrintable(i32); // The `derive` attribute automatically creates the implementation @@ -78,7 +78,7 @@ One can manually implement `fmt::Display` to control the display. and [`struct`][structs] [attributes]: https://doc.rust-lang.org/reference/attributes.html -[derive]: trait/derive.html +[derive]: ../../trait/derive.md [fmt]: https://doc.rust-lang.org/std/fmt/ -[structs]: custom_types/structs.html +[structs]: ../../custom_types/structs.md diff --git a/src/doc/rust-by-example/src/hello/print/print_display.md b/src/doc/rust-by-example/src/hello/print/print_display.md index dc86ff2edf..55ed8702ad 100644 --- a/src/doc/rust-by-example/src/hello/print/print_display.md +++ b/src/doc/rust-by-example/src/hello/print/print_display.md @@ -9,11 +9,11 @@ looks like this: // Import (via `use`) the `fmt` module to make it available. use std::fmt; -// Define a structure which `fmt::Display` will be implemented for. This is simply -// a tuple struct containing an `i32` bound to the name `Structure`. +// Define a structure for which `fmt::Display` will be implemented. This is +// a tuple struct named `Structure` that contains an `i32`. struct Structure(i32); -// In order to use the `{}` marker, the trait `fmt::Display` must be implemented +// To use the `{}` marker, the trait `fmt::Display` must be implemented // manually for the type. impl fmt::Display for Structure { // This trait requires `fmt` with this exact signature. @@ -30,7 +30,7 @@ impl fmt::Display for Structure { `fmt::Display` may be cleaner than `fmt::Debug` but this presents a problem for the `std` library. How should ambiguous types be displayed? For example, if the `std` library implemented a single style for all -`Vec`, what style should it be? Either of these two? +`Vec`, what style should it be? Would it be either of these two? * `Vec`: `/:/etc:/home/username:/bin` (split on `:`) * `Vec`: `1,2,3` (split on `,`) @@ -66,7 +66,7 @@ struct Point2D { y: f64, } -// Similarly, implement for Point2D +// Similarly, implement `Display` for `Point2D` impl fmt::Display for Point2D { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Customize so only `x` and `y` are denoted. @@ -94,7 +94,7 @@ fn main() { println!("Display: {}", point); println!("Debug: {:?}", point); - // Error. Both `Debug` and `Display` were implemented but `{:b}` + // Error. Both `Debug` and `Display` were implemented, but `{:b}` // requires `fmt::Binary` to be implemented. This will not work. // println!("What does Point2D look like in binary: {:b}?", point); } @@ -107,7 +107,7 @@ each requires its own implementation. This is detailed further in ### Activity -After checking the output of the above example, use the `Point2D` struct as +After checking the output of the above example, use the `Point2D` struct as a guide to add a Complex struct to the example. When printed in the same way, the output should be: @@ -121,9 +121,9 @@ Debug: Complex { real: 3.3, imag: 7.2 } [`derive`][derive], [`std::fmt`][fmt], [macros], [`struct`][structs], [`trait`][traits], and [use][use] -[derive]: trait/derive.html +[derive]: ../../trait/derive.md [fmt]: https://doc.rust-lang.org/std/fmt/ -[macros]: macros.html -[structs]: custom_types/structs.html -[traits]: trait.html -[use]: mod/use.html +[macros]: ../../macros.md +[structs]: ../../custom_types/structs.md +[traits]: ../../trait.md +[use]: ../../mod/use.md diff --git a/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md b/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md index d67d988bed..c44c022c62 100644 --- a/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md +++ b/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md @@ -32,7 +32,7 @@ struct List(Vec); impl fmt::Display for List { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // Extract the value using tuple indexing + // Extract the value using tuple indexing, // and create a reference to `vec`. let vec = &self.0; @@ -47,7 +47,7 @@ impl fmt::Display for List { write!(f, "{}", v)?; } - // Close the opened bracket and return a fmt::Result value + // Close the opened bracket and return a fmt::Result value. write!(f, "]") } } @@ -71,9 +71,9 @@ Try changing the program so that the index of each element in the vector is also [`for`][for], [`ref`][ref], [`Result`][result], [`struct`][struct], [`?`][q_mark], and [`vec!`][vec] -[for]: flow_control/for.html -[result]: std/result.html -[ref]: scope/borrow/ref.html -[struct]: custom_types/structs.html -[q_mark]: std/result/question_mark.html -[vec]: std/vec.html +[for]: ../../../flow_control/for.md +[result]: ../../../std/result.md +[ref]: ../../../scope/borrow/ref.md +[struct]: ../../../custom_types/structs.md +[q_mark]: ../../../std/result/question_mark.md +[vec]: ../../../std/vec.md diff --git a/src/doc/rust-by-example/src/index.md b/src/doc/rust-by-example/src/index.md index 5f1572f020..fecc1906aa 100644 --- a/src/doc/rust-by-example/src/index.md +++ b/src/doc/rust-by-example/src/index.md @@ -11,53 +11,53 @@ Additionally for the curious, you can also [check out the source code for this s Now let's begin! -- [Hello World](hello.html) - Start with a traditional Hello World program. +- [Hello World](hello.md) - Start with a traditional Hello World program. -- [Primitives](primitives.html) - Learn about signed integers, unsigned integers and other primitives. +- [Primitives](primitives.md) - Learn about signed integers, unsigned integers and other primitives. -- [Custom Types](custom_types.html) - `struct` and `enum`. +- [Custom Types](custom_types.md) - `struct` and `enum`. -- [Variable Bindings](variable_bindings.html) - mutable bindings, scope, shadowing. +- [Variable Bindings](variable_bindings.md) - mutable bindings, scope, shadowing. -- [Types](types.html) - Learn about changing and defining types. +- [Types](types.md) - Learn about changing and defining types. -- [Conversion](conversion.html) +- [Conversion](conversion.md) -- [Expressions](expression.html) +- [Expressions](expression.md) -- [Flow Control](flow_control.html) - `if`/`else`, `for`, and others. +- [Flow of Control](flow_control.md) - `if`/`else`, `for`, and others. -- [Functions](fn.html) - Learn about Methods, Closures and High Order Functions. +- [Functions](fn.md) - Learn about Methods, Closures and High Order Functions. -- [Modules](mod.html) - Organize code using modules +- [Modules](mod.md) - Organize code using modules -- [Crates](crates.html) - A crate is a compilation unit in Rust. Learn to create a library. +- [Crates](crates.md) - A crate is a compilation unit in Rust. Learn to create a library. -- [Cargo](cargo.html) - Go through some basic features of the official Rust package management tool. +- [Cargo](cargo.md) - Go through some basic features of the official Rust package management tool. -- [Attributes](attribute.html) - An attribute is metadata applied to some module, crate or item. +- [Attributes](attribute.md) - An attribute is metadata applied to some module, crate or item. -- [Generics](generics.html) - Learn about writing a function or data type which can work for multiple types of arguments. +- [Generics](generics.md) - Learn about writing a function or data type which can work for multiple types of arguments. -- [Scoping rules](scope.html) - Scopes play an important part in ownership, borrowing, and lifetimes. +- [Scoping rules](scope.md) - Scopes play an important part in ownership, borrowing, and lifetimes. -- [Traits](trait.html) - A trait is a collection of methods defined for an unknown type: `Self` +- [Traits](trait.md) - A trait is a collection of methods defined for an unknown type: `Self` -- [Macros](macros.html) +- [Macros](macros.md) -- [Error handling](error.html) - Learn Rust way of handling failures. +- [Error handling](error.md) - Learn Rust way of handling failures. -- [Std library types](std.html) - Learn about some custom types provided by `std` library. +- [Std library types](std.md) - Learn about some custom types provided by `std` library. -- [Std misc](std_misc.html) - More custom types for file handling, threads. +- [Std misc](std_misc.md) - More custom types for file handling, threads. -- [Testing](testing.html) - All sorts of testing in Rust. +- [Testing](testing.md) - All sorts of testing in Rust. -- [Unsafe Operations](unsafe.html) +- [Unsafe Operations](unsafe.md) -- [Compatibility](compatibility.html) +- [Compatibility](compatibility.md) -- [Meta](meta.html) - Documentation, Benchmarking. +- [Meta](meta.md) - Documentation, Benchmarking. [rust]: https://www.rust-lang.org/ diff --git a/src/doc/rust-by-example/src/macros.md b/src/doc/rust-by-example/src/macros.md index 0b27fc9935..ac727f463f 100644 --- a/src/doc/rust-by-example/src/macros.md +++ b/src/doc/rust-by-example/src/macros.md @@ -14,10 +14,10 @@ Macros are created using the `macro_rules!` macro. // This is a simple macro named `say_hello`. macro_rules! say_hello { // `()` indicates that the macro takes no argument. - () => ( + () => { // The macro will expand into the contents of this block. println!("Hello!"); - ) + }; } fn main() { diff --git a/src/doc/rust-by-example/src/macros/designators.md b/src/doc/rust-by-example/src/macros/designators.md index b2230ef420..78183030a8 100644 --- a/src/doc/rust-by-example/src/macros/designators.md +++ b/src/doc/rust-by-example/src/macros/designators.md @@ -8,13 +8,13 @@ macro_rules! create_function { // This macro takes an argument of designator `ident` and // creates a function named `$func_name`. // The `ident` designator is used for variable/function names. - ($func_name:ident) => ( + ($func_name:ident) => { fn $func_name() { // The `stringify!` macro converts an `ident` into a string. println!("You called {:?}()", stringify!($func_name)); } - ) + }; } // Create functions named `foo` and `bar` with the above macro. @@ -25,12 +25,12 @@ macro_rules! print_result { // This macro takes an expression of type `expr` and prints // it as a string along with its result. // The `expr` designator is used for expressions. - ($expression:expr) => ( + ($expression:expr) => { // `stringify!` will convert the expression *as it is* into a string. println!("{:?} = {:?}", stringify!($expression), $expression); - ) + }; } fn main() { diff --git a/src/doc/rust-by-example/src/macros/dry.md b/src/doc/rust-by-example/src/macros/dry.md index ffa8250687..a8c06112ca 100644 --- a/src/doc/rust-by-example/src/macros/dry.md +++ b/src/doc/rust-by-example/src/macros/dry.md @@ -10,18 +10,18 @@ use std::ops::{Add, Mul, Sub}; macro_rules! assert_equal_len { // The `tt` (token tree) designator is used for // operators and tokens. - ($a:ident, $b:ident, $func:ident, $op:tt) => ( + ($a:ident, $b:ident, $func:ident, $op:tt) => { assert!($a.len() == $b.len(), "{:?}: dimension mismatch: {:?} {:?} {:?}", stringify!($func), ($a.len(),), stringify!($op), ($b.len(),)); - ) + }; } macro_rules! op { - ($func:ident, $bound:ident, $op:tt, $method:ident) => ( + ($func:ident, $bound:ident, $op:tt, $method:ident) => { fn $func + Copy>(xs: &mut Vec, ys: &Vec) { assert_equal_len!(xs, ys, $func, $op); @@ -30,7 +30,7 @@ macro_rules! op { // *x = x.$method(*y); } } - ) + }; } // Implement `add_assign`, `mul_assign`, and `sub_assign` functions. @@ -54,7 +54,7 @@ mod test { assert_eq!(x, z); } } - } + }; } // Test `add_assign`, `mul_assign`, and `sub_assign`. diff --git a/src/doc/rust-by-example/src/macros/overload.md b/src/doc/rust-by-example/src/macros/overload.md index 6415e2e4dc..84d341a56a 100644 --- a/src/doc/rust-by-example/src/macros/overload.md +++ b/src/doc/rust-by-example/src/macros/overload.md @@ -9,19 +9,19 @@ In that regard, `macro_rules!` can work similarly to a match block: macro_rules! test { // Arguments don't need to be separated by a comma. // Any template can be used! - ($left:expr; and $right:expr) => ( + ($left:expr; and $right:expr) => { println!("{:?} and {:?} is {:?}", stringify!($left), stringify!($right), $left && $right) - ); + }; // ^ each arm must end with a semicolon. - ($left:expr; or $right:expr) => ( + ($left:expr; or $right:expr) => { println!("{:?} or {:?} is {:?}", stringify!($left), stringify!($right), $left || $right) - ); + }; } fn main() { diff --git a/src/doc/rust-by-example/src/macros/repeat.md b/src/doc/rust-by-example/src/macros/repeat.md index 2b00387972..a3431ef51c 100644 --- a/src/doc/rust-by-example/src/macros/repeat.md +++ b/src/doc/rust-by-example/src/macros/repeat.md @@ -22,7 +22,7 @@ macro_rules! find_min { fn main() { println!("{}", find_min!(1u32)); - println!("{}", find_min!(1u32 + 2 , 2u32)); + println!("{}", find_min!(1u32 + 2, 2u32)); println!("{}", find_min!(5u32, 2u32 * 3, 4u32)); } ``` \ No newline at end of file diff --git a/src/doc/rust-by-example/src/macros/syntax.md b/src/doc/rust-by-example/src/macros/syntax.md index 16082586f0..d00e2695c0 100644 --- a/src/doc/rust-by-example/src/macros/syntax.md +++ b/src/doc/rust-by-example/src/macros/syntax.md @@ -7,6 +7,6 @@ There are three basic ideas: - [Overloading][overloading] - [Repetition][repetition] -[designators]: macros/designators.html -[overloading]: macros/overload.html -[repetition]: macros/repeat.html +[designators]: designators.md +[overloading]: overload.md +[repetition]: repeat.md diff --git a/src/doc/rust-by-example/src/mod/split.md b/src/doc/rust-by-example/src/mod/split.md index 703b915ae9..a7d20aedac 100644 --- a/src/doc/rust-by-example/src/mod/split.md +++ b/src/doc/rust-by-example/src/mod/split.md @@ -93,4 +93,4 @@ called `my::indirect_access()`, that called `my::nested::function()` ``` -[visibility]: mod/visibility.html +[visibility]: visibility.md diff --git a/src/doc/rust-by-example/src/mod/struct_visibility.md b/src/doc/rust-by-example/src/mod/struct_visibility.md index e10c526e9a..e7359413c7 100644 --- a/src/doc/rust-by-example/src/mod/struct_visibility.md +++ b/src/doc/rust-by-example/src/mod/struct_visibility.md @@ -55,5 +55,5 @@ fn main() { [generics][generics] and [methods][methods] -[generics]: generics.html -[methods]: fn/methods.html \ No newline at end of file +[generics]: ../generics.md +[methods]: ../fn/methods.md \ No newline at end of file diff --git a/src/doc/rust-by-example/src/mod/visibility.md b/src/doc/rust-by-example/src/mod/visibility.md index 46c0b6abd1..2c3ca8b89a 100644 --- a/src/doc/rust-by-example/src/mod/visibility.md +++ b/src/doc/rust-by-example/src/mod/visibility.md @@ -56,7 +56,7 @@ mod my_mod { } pub fn call_public_function_in_my_mod() { - print!("called `my_mod::call_public_funcion_in_my_mod()`, that\n> "); + print!("called `my_mod::call_public_function_in_my_mod()`, that\n> "); nested::public_function_in_my_mod(); print!("> "); nested::public_function_in_super_mod(); diff --git a/src/doc/rust-by-example/src/primitives.md b/src/doc/rust-by-example/src/primitives.md index 14de0d74eb..dfa75068bc 100644 --- a/src/doc/rust-by-example/src/primitives.md +++ b/src/doc/rust-by-example/src/primitives.md @@ -58,6 +58,6 @@ fn main() { [the `std` library][std], [`mut`][mut], [inference], and [shadowing] [std]: https://doc.rust-lang.org/std/ -[mut]: variable_bindings/mut.html -[inference]: types/inference.html -[shadowing]: variable_bindings/scope.html +[mut]: variable_bindings/mut.md +[inference]: types/inference.md +[shadowing]: variable_bindings/scope.md diff --git a/src/doc/rust-by-example/src/primitives/tuples.md b/src/doc/rust-by-example/src/primitives/tuples.md index 253aa6fc26..7e29ef22c7 100644 --- a/src/doc/rust-by-example/src/primitives/tuples.md +++ b/src/doc/rust-by-example/src/primitives/tuples.md @@ -94,4 +94,4 @@ fn main() { ( 1.2 2.2 ) ``` -[print_display]: hello/print/print_display.html +[print_display]: ../hello/print/print_display.md diff --git a/src/doc/rust-by-example/src/scope/borrow/mut.md b/src/doc/rust-by-example/src/scope/borrow/mut.md index e9082b135b..62119bb483 100644 --- a/src/doc/rust-by-example/src/scope/borrow/mut.md +++ b/src/doc/rust-by-example/src/scope/borrow/mut.md @@ -56,4 +56,4 @@ fn main() { ### See also: [`static`][static] -[static]: scope/lifetime/static_lifetime.html +[static]: ../lifetime/static_lifetime.md diff --git a/src/doc/rust-by-example/src/scope/lifetime/elision.md b/src/doc/rust-by-example/src/scope/lifetime/elision.md index 9a7204b25d..d1897e7e62 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/elision.md +++ b/src/doc/rust-by-example/src/scope/lifetime/elision.md @@ -1,16 +1,16 @@ # Elision Some lifetime patterns are overwhelmingly common and so the borrow checker -will implicitly add them to save typing and to improve readability. -This process of implicit addition is called elision. Elision exists in Rust -solely because these patterns are common. +will allow you to omit them to save typing and to improve readability. +This is known as elision. Elision exists in Rust solely because these patterns +are common. The following code shows a few examples of elision. For a more comprehensive description of elision, see [lifetime elision][elision] in the book. ```rust,editable // `elided_input` and `annotated_input` essentially have identical signatures -// because the lifetime of `elided_input` is elided by the compiler: +// because the lifetime of `elided_input` is inferred by the compiler: fn elided_input(x: &i32) { println!("`elided_input`: {}", x); } diff --git a/src/doc/rust-by-example/src/scope/lifetime/explicit.md b/src/doc/rust-by-example/src/scope/lifetime/explicit.md index 89c1279183..ebd7b69017 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/explicit.md +++ b/src/doc/rust-by-example/src/scope/lifetime/explicit.md @@ -69,7 +69,7 @@ fn main() { [generics][generics] and [closures][closures] -[anonymity]: fn/closures/anonymity.html -[closures]: fn/closures.html -[elision]: scope/lifetime/elision.html -[generics]: generics.html +[anonymity]: ../../fn/closures/anonymity.md +[closures]: ../../fn/closures.md +[elision]: elision.md +[generics]: ../../generics.md diff --git a/src/doc/rust-by-example/src/scope/lifetime/fn.md b/src/doc/rust-by-example/src/scope/lifetime/fn.md index 64a1f5f7eb..6c5c8afe60 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/fn.md +++ b/src/doc/rust-by-example/src/scope/lifetime/fn.md @@ -59,5 +59,5 @@ fn main() { [functions][fn] -[elision]: scope/lifetime/elision.html -[fn]: fn.html +[elision]: elision.md +[fn]: fn.md diff --git a/src/doc/rust-by-example/src/scope/lifetime/lifetime_bounds.md b/src/doc/rust-by-example/src/scope/lifetime/lifetime_bounds.md index 8df5f96125..3d635bde1f 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/lifetime_bounds.md +++ b/src/doc/rust-by-example/src/scope/lifetime/lifetime_bounds.md @@ -48,6 +48,6 @@ fn main() { [generics][generics], [bounds in generics][bounds], and [multiple bounds in generics][multibounds] -[generics]: generics.html -[bounds]: generics/bounds.html -[multibounds]: generics/multi_bounds.html +[generics]: ../../generics.md +[bounds]: ../../generics/bounds.md +[multibounds]: ../../generics/multi_bounds.md diff --git a/src/doc/rust-by-example/src/scope/lifetime/methods.md b/src/doc/rust-by-example/src/scope/lifetime/methods.md index c7317c833a..1e1eb96f47 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/methods.md +++ b/src/doc/rust-by-example/src/scope/lifetime/methods.md @@ -25,4 +25,4 @@ fn main() { [methods] -[methods]: fn/methods.html +[methods]: ../../fn/methods.md diff --git a/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md b/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md index 917b6b7959..46d81117c8 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md +++ b/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md @@ -49,4 +49,4 @@ fn main() { [`'static` constants][static_const] -[static_const]: custom_types/constants.html \ No newline at end of file +[static_const]: ../../custom_types/constants.md \ No newline at end of file diff --git a/src/doc/rust-by-example/src/scope/lifetime/struct.md b/src/doc/rust-by-example/src/scope/lifetime/struct.md index 3b33da3ee6..aca0bfe622 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/struct.md +++ b/src/doc/rust-by-example/src/scope/lifetime/struct.md @@ -43,4 +43,4 @@ fn main() { [`struct`s][structs] -[structs]: custom_types/structs.html +[structs]: ../../custom_types/structs.md diff --git a/src/doc/rust-by-example/src/scope/lifetime/trait.md b/src/doc/rust-by-example/src/scope/lifetime/trait.md index c0808ae09a..0f56f5b4c1 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/trait.md +++ b/src/doc/rust-by-example/src/scope/lifetime/trait.md @@ -30,4 +30,4 @@ fn main() { [`trait`s][trait] -[trait]: trait.html +[trait]: ../../trait.md diff --git a/src/doc/rust-by-example/src/scope/move.md b/src/doc/rust-by-example/src/scope/move.md index 84372af8f2..0433e8ac1a 100644 --- a/src/doc/rust-by-example/src/scope/move.md +++ b/src/doc/rust-by-example/src/scope/move.md @@ -57,4 +57,4 @@ fn main() { } ``` -[references]: flow_control/match/destructuring/destructure_pointers.html +[references]: ../flow_control/match/destructuring/destructure_pointers.md diff --git a/src/doc/rust-by-example/src/scope/raii.md b/src/doc/rust-by-example/src/scope/raii.md index d5c00a5b97..2b2071707e 100644 --- a/src/doc/rust-by-example/src/scope/raii.md +++ b/src/doc/rust-by-example/src/scope/raii.md @@ -91,6 +91,6 @@ fn main() { [Box][box] [raii]: https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization -[box]: std/box.html +[box]: ../std/box.md [valgrind]: http://valgrind.org/info/ [`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html diff --git a/src/doc/rust-by-example/src/std.md b/src/doc/rust-by-example/src/std.md index debfc73f49..8863c788ae 100644 --- a/src/doc/rust-by-example/src/std.md +++ b/src/doc/rust-by-example/src/std.md @@ -13,5 +13,5 @@ the `primitives`. Some of these include: [primitives] and [the std library][std] -[primitives]: primitives.html +[primitives]: primitives.md [std]: https://doc.rust-lang.org/std/ diff --git a/src/doc/rust-by-example/src/std/box.md b/src/doc/rust-by-example/src/std/box.md index 64856d7aa7..8d45e1a44e 100644 --- a/src/doc/rust-by-example/src/std/box.md +++ b/src/doc/rust-by-example/src/std/box.md @@ -1,9 +1,9 @@ # Box, stack and heap All values in Rust are stack allocated by default. Values can be *boxed* -(allocated in the heap) by creating a `Box`. A box is a smart pointer to a +(allocated on the heap) by creating a `Box`. A box is a smart pointer to a heap allocated value of type `T`. When a box goes out of scope, its destructor -is called, the inner object is destroyed, and the memory in the heap is freed. +is called, the inner object is destroyed, and the memory on the heap is freed. Boxed values can be dereferenced using the `*` operator; this removes one layer of indirection. @@ -29,7 +29,7 @@ fn origin() -> Point { } fn boxed_origin() -> Box { - // Allocate this point in the heap, and return a pointer to it + // Allocate this point on the heap, and return a pointer to it Box::new(Point { x: 0.0, y: 0.0 }) } @@ -54,22 +54,22 @@ fn main() { // Double indirection let box_in_a_box: Box> = Box::new(boxed_origin()); - println!("Point occupies {} bytes in the stack", + println!("Point occupies {} bytes on the stack", mem::size_of_val(&point)); - println!("Rectangle occupies {} bytes in the stack", + println!("Rectangle occupies {} bytes on the stack", mem::size_of_val(&rectangle)); - // box size = pointer size - println!("Boxed point occupies {} bytes in the stack", + // box size == pointer size + println!("Boxed point occupies {} bytes on the stack", mem::size_of_val(&boxed_point)); - println!("Boxed rectangle occupies {} bytes in the stack", + println!("Boxed rectangle occupies {} bytes on the stack", mem::size_of_val(&boxed_rectangle)); - println!("Boxed box occupies {} bytes in the stack", + println!("Boxed box occupies {} bytes on the stack", mem::size_of_val(&box_in_a_box)); // Copy the data contained in `boxed_point` into `unboxed_point` let unboxed_point: Point = *boxed_point; - println!("Unboxed point occupies {} bytes in the stack", + println!("Unboxed point occupies {} bytes on the stack", mem::size_of_val(&unboxed_point)); } ``` \ No newline at end of file diff --git a/src/doc/rust-by-example/src/std_misc.md b/src/doc/rust-by-example/src/std_misc.md index 5106b934de..ac9c57864f 100644 --- a/src/doc/rust-by-example/src/std_misc.md +++ b/src/doc/rust-by-example/src/std_misc.md @@ -13,5 +13,5 @@ These expand beyond what the [primitives] provide. [primitives] and [the std library][std] -[primitives]: primitives.html +[primitives]: primitives.md [std]: https://doc.rust-lang.org/std/ diff --git a/src/doc/rust-by-example/src/std_misc/fs.md b/src/doc/rust-by-example/src/std_misc/fs.md index 42eccf3ef5..0374c5a205 100644 --- a/src/doc/rust-by-example/src/std_misc/fs.md +++ b/src/doc/rust-by-example/src/std_misc/fs.md @@ -143,4 +143,4 @@ fn cat(path: &Path) -> io::Result { [`cfg!`][cfg] -[cfg]: attribute/cfg.html +[cfg]: ../attribute/cfg.md diff --git a/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md b/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md index 6de19e0931..9efc34a87f 100644 --- a/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md +++ b/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md @@ -140,13 +140,13 @@ defined by a static constant at the beginning of the program. * [unwrap vs. expect][unwrap] * [enumerate][enumerate] -[thread]: std_misc/threads.html -[vectors]: std/vec.html -[iterators]: trait/iter.html +[thread]: ../threads.md +[vectors]: ../../std/vec.md +[iterators]: ../../trait/iter.md [destructuring]: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#destructuring-to-break-apart-values -[closures]: fn/closures.html -[move]: scope/move.html +[closures]: ../../fn/closures.md +[move]: ../../scope/move.md [move_closure]: https://doc.rust-lang.org/book/ch13-01-closures.html#closures-can-capture-their-environment [turbofish]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect -[unwrap]: error/option_unwrap.html +[unwrap]: ../../error/option_unwrap.md [enumerate]: https://doc.rust-lang.org/book/loops.html#enumerate diff --git a/src/doc/rust-by-example/src/testing.md b/src/doc/rust-by-example/src/testing.md index b94462474e..6de0ca63fd 100644 --- a/src/doc/rust-by-example/src/testing.md +++ b/src/doc/rust-by-example/src/testing.md @@ -18,9 +18,9 @@ Also Rust has support for specifying additional dependencies for tests: * [The Book][doc-testing] chapter on testing * [API Guidelines][doc-nursery] on doc-testing -[unit]: testing/unit_testing.html -[doc]: testing/doc_testing.html -[integration]: testing/integration_testing.html -[dev-dependencies]: testing/dev_dependencies.html +[unit]: testing/unit_testing.md +[doc]: testing/doc_testing.md +[integration]: testing/integration_testing.md +[dev-dependencies]: testing/dev_dependencies.md [doc-testing]: https://doc.rust-lang.org/book/ch11-00-testing.html [doc-nursery]: https://rust-lang-nursery.github.io/api-guidelines/documentation.html diff --git a/src/doc/rust-by-example/src/testing/integration_testing.md b/src/doc/rust-by-example/src/testing/integration_testing.md index ba66ff0242..d0e5122b51 100644 --- a/src/doc/rust-by-example/src/testing/integration_testing.md +++ b/src/doc/rust-by-example/src/testing/integration_testing.md @@ -83,5 +83,5 @@ fn test_add() { Modules with common code follow the ordinary [modules][mod] rules, so it's ok to create common module as `tests/common/mod.rs`. -[unit]: testing/unit_testing.html -[mod]: mod.html +[unit]: unit_testing.md +[mod]: ../mod.md diff --git a/src/doc/rust-by-example/src/testing/unit_testing.md b/src/doc/rust-by-example/src/testing/unit_testing.md index 252577f0ef..a6060e9c0d 100644 --- a/src/doc/rust-by-example/src/testing/unit_testing.md +++ b/src/doc/rust-by-example/src/testing/unit_testing.md @@ -224,7 +224,7 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` -[attribute]: attribute.html -[panic]: std/panic.html -[macros]: macros.html -[mod]: mod.html +[attribute]: ../attribute.md +[panic]: ../std/panic.md +[macros]: ../macros.md +[mod]: ../mod.md diff --git a/src/doc/rust-by-example/src/trait/derive.md b/src/doc/rust-by-example/src/trait/derive.md index ff37bffc67..4769efe627 100644 --- a/src/doc/rust-by-example/src/trait/derive.md +++ b/src/doc/rust-by-example/src/trait/derive.md @@ -30,7 +30,7 @@ impl Inches { } } -// `Seconds`, a tuple struct no additional attributes +// `Seconds`, a tuple struct with no additional attributes struct Seconds(i32); fn main() { @@ -64,7 +64,7 @@ fn main() { ### See also: [`derive`][derive] -[attribute]: attribute.html +[attribute]: ../attribute.md [eq]: https://doc.rust-lang.org/std/cmp/trait.Eq.html [partial-eq]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html [ord]: https://doc.rust-lang.org/std/cmp/trait.Ord.html diff --git a/src/doc/rust-by-example/src/types.md b/src/doc/rust-by-example/src/types.md index 04088a96f0..1d3b50aaba 100644 --- a/src/doc/rust-by-example/src/types.md +++ b/src/doc/rust-by-example/src/types.md @@ -7,7 +7,7 @@ user defined types. The following sections cover: * Using [type inference] * [Aliasing] types -[Casting]: types/cast.html -[literals]: types/literals.html -[type inference]: types/inference.html -[Aliasing]: types/alias.html +[Casting]: types/cast.md +[literals]: types/literals.md +[type inference]: types/inference.md +[Aliasing]: types/alias.md diff --git a/src/doc/rust-by-example/src/types/alias.md b/src/doc/rust-by-example/src/types/alias.md index 3c3bed0162..c839f53213 100644 --- a/src/doc/rust-by-example/src/types/alias.md +++ b/src/doc/rust-by-example/src/types/alias.md @@ -33,4 +33,4 @@ is an alias for the `Result` type. ### See also: -[Attributes](attribute.html) \ No newline at end of file +[Attributes](../attribute.md) \ No newline at end of file diff --git a/src/doc/rust-by-example/src/types/literals.md b/src/doc/rust-by-example/src/types/literals.md index db2b7323f2..78aa67fbe3 100644 --- a/src/doc/rust-by-example/src/types/literals.md +++ b/src/doc/rust-by-example/src/types/literals.md @@ -38,6 +38,6 @@ yet, here's a brief explanation for the impatient readers: is defined in the `std` *crate*. For more details, see [modules][mod] and [crates][crate]. -[borrow]: scope/borrow.html -[mod]: mod.html -[crate]: crates.html +[borrow]: ../scope/borrow.md +[mod]: ../mod.md +[crate]: ../crates.md diff --git a/src/doc/rust-by-example/src/unsafe.md b/src/doc/rust-by-example/src/unsafe.md index 742762c279..1eeec6ba35 100644 --- a/src/doc/rust-by-example/src/unsafe.md +++ b/src/doc/rust-by-example/src/unsafe.md @@ -8,7 +8,7 @@ things that unsafe is used for: * dereferencing raw pointers * calling functions or methods which are `unsafe` (including calling a function - over FFI, see [a previous chapter](std_misc/ffi.html) of the book) + over FFI, see [a previous chapter](std_misc/ffi.md) of the book) * accessing or modifying static mutable variables * implementing unsafe traits diff --git a/src/doc/rustc-guide/ci/install.sh b/src/doc/rustc-guide/ci/install.sh index 835f231925..7c730cae33 100755 --- a/src/doc/rustc-guide/ci/install.sh +++ b/src/doc/rustc-guide/ci/install.sh @@ -20,5 +20,5 @@ function cargo_install() { fi } -cargo_install mdbook 0.2.3 -cargo_install mdbook-linkcheck 0.2.3 +cargo_install mdbook 0.3.0 +cargo_install mdbook-linkcheck 0.3.0 diff --git a/src/doc/rustc-guide/src/SUMMARY.md b/src/doc/rustc-guide/src/SUMMARY.md index 477b9a7073..8c8890b799 100644 --- a/src/doc/rustc-guide/src/SUMMARY.md +++ b/src/doc/rustc-guide/src/SUMMARY.md @@ -5,86 +5,92 @@ --- - [Part 1: Building, debugging, and contributing to Rustc](./part-1-intro.md) -- [About the compiler team](./compiler-team.md) -- [How to build the compiler and run what you built](./how-to-build-and-run.md) - - [Build and Install distribution artifacts](./build-install-distribution-artifacts.md) - - [Documenting Compiler](./compiler-documenting.md) -- [The compiler testing framework](./tests/intro.md) - - [Running tests](./tests/running.md) - - [Adding new tests](./tests/adding.md) - - [Using `compiletest` + commands to control test execution](./compiletest.md) -- [Walkthrough: a typical contribution](./walkthrough.md) -- [Implementing new features](./implementing_new_features.md) -- [Stabilizing Features](./stabilization_guide.md) -- [Debugging the Compiler](./compiler-debugging.md) -- [Profiling the compiler](./profiling.md) - - [with the linux perf tool](./profiling/with_perf.md) -- [Coding conventions](./conventions.md) -- [crates.io Dependencies](./crates-io.md) - ---- - + - [About the compiler team](./compiler-team.md) + - [How to Build and Run the Compiler](./how-to-build-and-run.md) + - [Build and Install distribution artifacts](./build-install-distribution-artifacts.md) + - [Documenting Compiler](./compiler-documenting.md) + - [The compiler testing framework](./tests/intro.md) + - [Running tests](./tests/running.md) + - [Adding new tests](./tests/adding.md) + - [Using `compiletest` + commands to control test execution](./compiletest.md) + - [Walkthrough: a typical contribution](./walkthrough.md) + - [Implementing new features](./implementing_new_features.md) + - [Stabilizing Features](./stabilization_guide.md) + - [Debugging the Compiler](./compiler-debugging.md) + - [Profiling the compiler](./profiling.md) + - [with the linux perf tool](./profiling/with_perf.md) + - [Coding conventions](./conventions.md) + - [crates.io Dependencies](./crates-io.md) + - [Emitting Errors and other Diagnostics](diagnostics.md) + - [JSON diagnostic format](diagnostics/json-format.md) - [Part 2: How rustc works](./part-2-intro.md) -- [High-level overview of the compiler source](./high-level-overview.md) -- [The Rustc Driver and Interface](./rustc-driver.md) - - [Rustdoc](./rustdoc.md) -- [Queries: demand-driven compilation](./query.md) - - [The Query Evaluation Model in Detail](./queries/query-evaluation-model-in-detail.md) - - [Incremental compilation](./queries/incremental-compilation.md) - - [Incremental compilation In Detail](./queries/incremental-compilation-in-detail.md) - - [Debugging and Testing](./incrcomp-debugging.md) -- [The parser](./the-parser.md) -- [`#[test]` Implementation](./test-implementation.md) -- [Macro expansion](./macro-expansion.md) -- [Name resolution](./name-resolution.md) -- [The HIR (High-level IR)](./hir.md) - - [Lowering AST to HIR](./lowering.md) - - [Debugging](./hir-debugging.md) -- [The `ty` module: representing types](./ty.md) -- [Kinds](./kinds.md) -- [Type inference](./type-inference.md) -- [Trait solving (old-style)](./traits/resolution.md) - - [Higher-ranked trait bounds](./traits/hrtb.md) - - [Caching subtleties](./traits/caching.md) - - [Specialization](./traits/specialization.md) -- [Trait solving (new-style)](./traits/index.md) - - [Lowering to logic](./traits/lowering-to-logic.md) - - [Goals and clauses](./traits/goals-and-clauses.md) - - [Equality and associated types](./traits/associated-types.md) - - [Implied bounds](./traits/implied-bounds.md) - - [Region constraints](./traits/regions.md) - - [The lowering module in rustc](./traits/lowering-module.md) - - [Lowering rules](./traits/lowering-rules.md) - - [Well-formedness checking](./traits/wf.md) - - [Canonical queries](./traits/canonical-queries.md) - - [Canonicalization](./traits/canonicalization.md) - - [The SLG solver](./traits/slg.md) - - [An Overview of Chalk](./traits/chalk-overview.md) - - [Bibliography](./traits/bibliography.md) -- [Type checking](./type-checking.md) - - [Method Lookup](./method-lookup.md) - - [Variance](./variance.md) - - [Existential Types](./existential-types.md) -- [The MIR (Mid-level IR)](./mir/index.md) - - [MIR construction](./mir/construction.md) - - [MIR visitor and traversal](./mir/visitor.md) - - [MIR passes: getting the MIR for a function](./mir/passes.md) - - [MIR optimizations](./mir/optimizations.md) - - [Debugging](./mir/debugging.md) -- [The borrow checker](./borrow_check.md) - - [Tracking moves and initialization](./borrow_check/moves_and_initialization.md) - - [Move paths](./borrow_check/moves_and_initialization/move_paths.md) - - [MIR type checker](./borrow_check/type_check.md) - - [Region inference](./borrow_check/region_inference.md) - - [Two-phase-borrows](./borrow_check/two_phase_borrows.md) -- [Constant evaluation](./const-eval.md) - - [miri const evaluator](./miri.md) -- [Parameter Environments](./param_env.md) -- [Code Generation](./codegen.md) - - [Updating LLVM](./codegen/updating-llvm.md) - - [Debugging LLVM](./codegen/debugging.md) -- [Emitting Diagnostics](./diag.md) - - [JSON diagnostic format](./diag/json-format.md) + - [High-level overview of the compiler source](./high-level-overview.md) + - [The Rustc Driver and Interface](./rustc-driver.md) + - [Rustdoc](./rustdoc.md) + - [Queries: demand-driven compilation](./query.md) + - [The Query Evaluation Model in Detail](./queries/query-evaluation-model-in-detail.md) + - [Incremental compilation](./queries/incremental-compilation.md) + - [Incremental compilation In Detail](./queries/incremental-compilation-in-detail.md) + - [Debugging and Testing](./incrcomp-debugging.md) + - [The parser](./the-parser.md) + - [`#[test]` Implementation](./test-implementation.md) + - [Macro expansion](./macro-expansion.md) + - [Name resolution](./name-resolution.md) + - [The HIR (High-level IR)](./hir.md) + - [Lowering AST to HIR](./lowering.md) + - [Debugging](./hir-debugging.md) + - [Closure expansion](./closure.md) + - [The `ty` module: representing types](./ty.md) + - [Kinds](./kinds.md) + - [Type inference](./type-inference.md) + - [Trait solving (old-style)](./traits/resolution.md) + - [Higher-ranked trait bounds](./traits/hrtb.md) + - [Caching subtleties](./traits/caching.md) + - [Specialization](./traits/specialization.md) + - [Trait solving (new-style)](./traits/index.md) + - [Lowering to logic](./traits/lowering-to-logic.md) + - [Goals and clauses](./traits/goals-and-clauses.md) + - [Equality and associated types](./traits/associated-types.md) + - [Implied bounds](./traits/implied-bounds.md) + - [Region constraints](./traits/regions.md) + - [The lowering module in rustc](./traits/lowering-module.md) + - [Lowering rules](./traits/lowering-rules.md) + - [Well-formedness checking](./traits/wf.md) + - [Canonical queries](./traits/canonical-queries.md) + - [Canonicalization](./traits/canonicalization.md) + - [The SLG solver](./traits/slg.md) + - [An Overview of Chalk](./traits/chalk-overview.md) + - [Bibliography](./traits/bibliography.md) + - [Type checking](./type-checking.md) + - [Method Lookup](./method-lookup.md) + - [Variance](./variance.md) + - [Existential Types](./existential-types.md) + - [The MIR (Mid-level IR)](./mir/index.md) + - [MIR construction](./mir/construction.md) + - [MIR visitor and traversal](./mir/visitor.md) + - [MIR passes: getting the MIR for a function](./mir/passes.md) + - [MIR optimizations](./mir/optimizations.md) + - [Debugging](./mir/debugging.md) + - [The borrow checker](./borrow_check.md) + - [Tracking moves and initialization](./borrow_check/moves_and_initialization.md) + - [Move paths](./borrow_check/moves_and_initialization/move_paths.md) + - [MIR type checker](./borrow_check/type_check.md) + - [Region inference](./borrow_check/region_inference.md) + - [Constraint propagation](./borrow_check/region_inference/constraint_propagation.md) + - [Lifetime parameters](./borrow_check/region_inference/lifetime_parameters.md) + - [Member constraints](./borrow_check/region_inference/member_constraints.md) + - [Placeholders and universes][pau] + - [Closure constraints](./borrow_check/region_inference/closure_constraints.md) + - [Errror reporting](./borrow_check/region_inference/error_reporting.md) + - [Two-phase-borrows](./borrow_check/two_phase_borrows.md) + - [Constant evaluation](./const-eval.md) + - [miri const evaluator](./miri.md) + - [Parameter Environments](./param_env.md) + - [Code Generation](./codegen.md) + - [Updating LLVM](./codegen/updating-llvm.md) + - [Debugging LLVM](./codegen/debugging.md) + - [Profile-guided Optimization](./profile-guided-optimization.md) + - [Debugging Support in Rust Compiler](./debugging-support-in-rustc.md) --- @@ -92,4 +98,7 @@ [Appendix B: Background material](./appendix/background.md) [Appendix C: Glossary](./appendix/glossary.md) [Appendix D: Code Index](./appendix/code-index.md) +[Appendix E: Bibliography](./appendix/bibliography.md) [](./important-links.md) + +[pau]: ./borrow_check/region_inference/placeholders_and_universes.md diff --git a/src/doc/rustc-guide/src/about-this-guide.md b/src/doc/rustc-guide/src/about-this-guide.md index 30a3b88708..df060a2088 100644 --- a/src/doc/rustc-guide/src/about-this-guide.md +++ b/src/doc/rustc-guide/src/about-this-guide.md @@ -16,4 +16,16 @@ be found at the [GitHub repository]. If you find any mistakes in the guide, please file an issue about it, or even better, open a PR with a correction! +## Other places to find information + +You might also find the following sites useful: + +- [Rustc API docs] -- rustdoc documentation for the compiler +- [Forge] -- contains documentation about rust infrastructure, team procedures, and more +- [compiler-team] -- the home-base for the rust compiler team, with description + of the team procedures, active working groups, and the team calendar. + [GitHub repository]: https://github.com/rust-lang/rustc-guide/ +[Rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ +[Forge]: https://forge.rust-lang.org/ +[compiler-team]: https://github.com/rust-lang/compiler-team/ diff --git a/src/doc/rustc-guide/src/appendix/bibliography.md b/src/doc/rustc-guide/src/appendix/bibliography.md new file mode 100644 index 0000000000..19a9217f70 --- /dev/null +++ b/src/doc/rustc-guide/src/appendix/bibliography.md @@ -0,0 +1,90 @@ +# Rust Bibliography + +This is a reading list of material relevant to Rust. It includes prior +research that has - at one time or another - influenced the design of +Rust, as well as publications about Rust. + +## Type system + +* [Region based memory management in Cyclone](https://www.cs.umd.edu/projects/cyclone/papers/cyclone-regions.pdf) +* [Safe manual memory management in Cyclone](http://www.cs.umd.edu/projects/PL/cyclone/scp.pdf) +* [Typeclasses: making ad-hoc polymorphism less ad hoc](http://www.ps.uni-sb.de/courses/typen-ws99/class.ps.gz) +* [Macros that work together](https://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf) +* [Traits: composable units of behavior](http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf) +* [Alias burying](http://www.cs.uwm.edu/faculty/boyland/papers/unique-preprint.ps) - We tried something similar and abandoned it. +* [External uniqueness is unique enough](http://www.cs.uu.nl/research/techreps/UU-CS-2002-048.html) +* [Uniqueness and Reference Immutability for Safe Parallelism](https://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf) +* [Region Based Memory Management](http://www.cs.ucla.edu/~palsberg/tba/papers/tofte-talpin-iandc97.pdf) + +## Concurrency + +* [Singularity: rethinking the software stack](https://research.microsoft.com/pubs/69431/osr2007_rethinkingsoftwarestack.pdf) +* [Language support for fast and reliable message passing in singularity OS](https://research.microsoft.com/pubs/67482/singsharp.pdf) +* [Scheduling multithreaded computations by work stealing](http://supertech.csail.mit.edu/papers/steal.pdf) +* [Thread scheduling for multiprogramming multiprocessors](http://www.eecis.udel.edu/%7Ecavazos/cisc879-spring2008/papers/arora98thread.pdf) +* [The data locality of work stealing](http://www.aladdin.cs.cmu.edu/papers/pdfs/y2000/locality_spaa00.pdf) +* [Dynamic circular work stealing deque](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf) - The Chase/Lev deque +* [Work-first and help-first scheduling policies for async-finish task parallelism](http://www.cs.rice.edu/%7Eyguo/pubs/PID824943.pdf) - More general than fully-strict work stealing +* [A Java fork/join calamity](http://www.coopsoft.com/ar/CalamityArticle.html) - critique of Java's fork/join library, particularly its application of work stealing to non-strict computation +* [Scheduling techniques for concurrent systems](http://www.stanford.edu/~ouster/cgi-bin/papers/coscheduling.pdf) +* [Contention aware scheduling](http://www.blagodurov.net/files/a8-blagodurov.pdf) +* [Balanced work stealing for time-sharing multicores](http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/papers/TR-12-1.pdf) +* [Three layer cake for shared-memory programming](http://dl.acm.org/citation.cfm?id=1953616&dl=ACM&coll=DL&CFID=524387192&CFTOKEN=44362705) +* [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf) +* [Reagents: expressing and composing fine-grained concurrency](http://aturon.github.io/academic/reagents.pdf) +* [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf) +* [Epoch-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf). + +## Others + +* [Crash-only software](https://www.usenix.org/legacy/events/hotos03/tech/full_papers/candea/candea.pdf) +* [Composing High-Performance Memory Allocators](http://people.cs.umass.edu/~emery/pubs/berger-pldi2001.pdf) +* [Reconsidering Custom Memory Allocation](http://people.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf) + +## Papers *about* Rust + +* [GPU Programming in Rust: Implementing High Level Abstractions in a Systems + Level + Language](https://www.cs.indiana.edu/~achauhan/Publications/Pubs/2013-hips-holk-rust.pdf). + Early GPU work by Eric Holk. +* [Parallel closures: a new twist on an old + idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea) + - not exactly about Rust, but by nmatsakis +* [Patina: A Formalization of the Rust Programming + Language](http://dada.cs.washington.edu/research/tr/2015/03/UW-CSE-15-03-02.pdf). + Early formalization of a subset of the type system, by Eric Reed. +* [Experience Report: Developing the Servo Web Browser Engine using + Rust](http://arxiv.org/abs/1505.07383). By Lars Bergstrom. +* [Implementing a Generic Radix Trie in + Rust](https://michaelsproul.github.io/rust_radix_paper/rust-radix-sproul.pdf). Undergrad + paper by Michael Sproul. +* [Reenix: Implementing a Unix-Like Operating System in + Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex + Light. +* [Evaluation of performance and productivity metrics of potential programming languages in the HPC environment](http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf). + Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust. +* [Nom, a byte oriented, streaming, zero copy, parser combinators library + in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By + Geoffroy Couprie, research for VLC. +* [Graph-Based Higher-Order Intermediate + Representation](http://compilers.cs.uni-saarland.de/papers/lkh15_cgo.pdf). An + experimental IR implemented in Impala, a Rust-like language. +* [Code Refinement of Stencil + Codes](http://compilers.cs.uni-saarland.de/papers/ppl14_web.pdf). Another + paper using Impala. +* [Parallelization in Rust with fork-join and + friends](http://publications.lib.chalmers.se/records/fulltext/219016/219016.pdf). Linus + Farnstrand's master's thesis. +* [Session Types for + Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip + Munksgaard's master's thesis. Research for Servo. +* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf) +* [You can't spell trust without Rust](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf). Alexis Beingessner's master's thesis. +* [Rust-Bio: a fast and safe bioinformatics library](http://bioinformatics.oxfordjournals.org/content/early/2015/10/06/bioinformatics.btv573). Johannes Köster +* [Safe, Correct, and Fast Low-Level Networking](https://octarineparrot.com/assets/msci_paper.pdf). Robert Clipsham's master's thesis. +* [Formalizing Rust traits](http://hdl.handle.net/2429/55609). Jonatan Milewski's master's thesis. +* [Rust as a Language for High Performance GC Implementation](http://users.cecs.anu.edu.au/~steveb/downloads/pdf/rust-ismm-2016.pdf) +* [Simple Verification of Rust Programs via Functional Purification](https://github.com/Kha/electrolysis). Sebastian Ullrich's master's thesis. +* [Writing parsers like it is 2017](http://spw17.langsec.org/papers/chifflier-parsing-in-2017.pdf) Pierre Chifflier and Geoffroy Couprie for the Langsec Workshop +* [The Case for Writing a Kernel in Rust](https://www.tockos.org/assets/papers/rust-kernel-apsys2017.pdf) +* [RustBelt: Securing the Foundations of the Rust Programming Language](https://plv.mpi-sws.org/rustbelt/popl18/) diff --git a/src/doc/rustc-guide/src/appendix/code-index.md b/src/doc/rustc-guide/src/appendix/code-index.md index 3c71d6bbaa..52a7f42d6f 100644 --- a/src/doc/rustc-guide/src/appendix/code-index.md +++ b/src/doc/rustc-guide/src/appendix/code-index.md @@ -29,7 +29,7 @@ Item | Kind | Short description | Chapter | `TraitDef` | struct | This struct contains a trait's definition with type information | [The `ty` modules] | [src/librustc/ty/trait_def.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/trait_def/struct.TraitDef.html) `TraitRef` | struct | The combination of a trait and its input types (e.g. `P0: Trait`) | [Trait Solving: Goals and Clauses], [Trait Solving: Lowering impls] | [src/librustc/ty/sty.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TraitRef.html) `Ty<'tcx>` | struct | This is the internal representation of a type used for type checking | [Type checking] | [src/librustc/ty/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/type.Ty.html) -`TyCtxt<'cx, 'tcx, 'tcx>` | struct | The "typing context". This is the central data structure in the compiler. It is the context that you use to perform all manner of queries | [The `ty` modules] | [src/librustc/ty/context.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TyCtxt.html) +`TyCtxt<'tcx>` | struct | The "typing context". This is the central data structure in the compiler. It is the context that you use to perform all manner of queries | [The `ty` modules] | [src/librustc/ty/context.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TyCtxt.html) [The HIR]: ../hir.html [Identifiers in the HIR]: ../hir.html#hir-id @@ -38,7 +38,7 @@ Item | Kind | Short description | Chapter | [Type checking]: ../type-checking.html [The `ty` modules]: ../ty.html [Rustdoc]: ../rustdoc.html -[Emitting Diagnostics]: ../diag.html +[Emitting Diagnostics]: ../diagnostics.html [Macro expansion]: ../macro-expansion.html [Name resolution]: ../name-resolution.html [Parameter Environment]: ../param_env.html diff --git a/src/doc/rustc-guide/src/appendix/glossary.md b/src/doc/rustc-guide/src/appendix/glossary.md index a5d5bf56aa..007b1bb4cd 100644 --- a/src/doc/rustc-guide/src/appendix/glossary.md +++ b/src/doc/rustc-guide/src/appendix/glossary.md @@ -25,7 +25,6 @@ early-bound lifetime | a lifetime region that is substituted at its definiti empty type | see "uninhabited type". Fat pointer | a two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers". free variable | a "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.html#free-vs-bound) -'gcx | the lifetime of the global arena ([see more](../ty.html)) generics | the set of generic type parameters defined on a type or item HIR | the High-level IR, created by lowering and desugaring the AST ([see more](../hir.html)) HirId | identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". @@ -51,6 +50,7 @@ newtype | a "newtype" is a wrapper around some other type (e.g. NLL | [non-lexical lifetimes](../borrow_check/region_inference.html), an extension to Rust's borrowing system to make it be based on the control-flow graph. node-id or NodeId | an index identifying a particular node in the AST or HIR; gradually being phased out and replaced with `HirId`. obligation | something that must be proven by the trait system ([see more](../traits/resolution.html)) +point | used in the NLL analysis to refer to some particular location in the MIR; typically used to refer to a node in the control-flow graph. projection | a general term for a "relative path", e.g. `x.f` is a "field projection", and `T::Item` is an ["associated type projection"](../traits/goals-and-clauses.html#trait-ref) promoted constants | constants extracted from a function and lifted to static scope; see [this section](../mir/index.html#promoted) for more details. provider | the function that executes a query ([see more](../query.html)) @@ -66,7 +66,7 @@ soundness | soundness is a technical term in type theory. Roughly span | a location in the user's source code, used for error reporting primarily. These are like a file-name/line-number/column tuple on steroids: they carry a start/end point, and also track macro expansions and compiler desugaring. All while being packed into a few bytes (really, it's an index into a table). See the Span datatype for more. substs | the substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap`) tcx | the "typing context", main data structure of the compiler ([see more](../ty.html)) -'tcx | the lifetime of the currently active inference context ([see more](../ty.html)) +'tcx | the lifetime of the allocation arena ([see more](../ty.html)) trait reference | the name of a trait along with a suitable set of input type/lifetimes ([see more](../traits/goals-and-clauses.html#trait-ref)) token | the smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.html)). [TLS] | Thread-Local Storage. Variables may be defined so that each thread has its own copy (rather than all threads sharing the variable). This has some interactions with LLVM. Not all platforms support TLS. diff --git a/src/doc/rustc-guide/src/borrow_check/moves_and_initialization.md b/src/doc/rustc-guide/src/borrow_check/moves_and_initialization.md index d1530d6c09..043db2f535 100644 --- a/src/doc/rustc-guide/src/borrow_check/moves_and_initialization.md +++ b/src/doc/rustc-guide/src/borrow_check/moves_and_initialization.md @@ -7,7 +7,7 @@ figuring out where moves occur and tracking those. ## Initialization and moves From a user's perspective, initialization -- giving a variable some -value -- and moves -- transfering ownership to another place -- might +value -- and moves -- transferring ownership to another place -- might seem like distinct topics. Indeed, our borrow checker error messages often talk about them differently. But **within the borrow checker**, they are not nearly as separate. Roughly speaking, the borrow checker diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference.md b/src/doc/rustc-guide/src/borrow_check/region_inference.md index 7fe50b870c..46caab567c 100644 --- a/src/doc/rustc-guide/src/borrow_check/region_inference.md +++ b/src/doc/rustc-guide/src/borrow_check/region_inference.md @@ -24,20 +24,19 @@ The MIR-based region analysis consists of two major functions: - [`compute_regions`], invoked second: this is given as argument the results of move analysis. It has the job of computing values for all the inference variables that `replace_regions_in_mir` introduced. - - To do that, it first runs the [MIR type checker]. This - is basically a normal type-checker but specialized to MIR, which - is much simpler than full Rust, of course. Running the MIR type - checker will however create **outlives constraints** between - region variables (e.g., that one variable must outlive another - one) to reflect the subtyping relationships that arise. - - It also adds **liveness constraints** that arise from where variables - are used. - - After this, we create a [`RegionInferenceContext`] with the constraints we - have computed and the inference variables we introduced and use the - [`solve`] method to infer values for all region inference varaibles. + - To do that, it first runs the [MIR type checker]. This is + basically a normal type-checker but specialized to MIR, which is + much simpler than full Rust, of course. Running the MIR type + checker will however create various [constraints][cp] between region + variables, indicating their potential values and relationships to + one another. + - After this, we perform [constraint propagation][cp] by creating a + [`RegionInferenceContext`] and invoking its [`solve`] + method. - The [NLL RFC] also includes fairly thorough (and hopefully readable) coverage. +[cp]: ./region_inference/constraint_propagation.html [fvb]: ../appendix/background.html#free-vs-bound [`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.replace_regions_in_mir.html [`compute_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.compute_regions.html @@ -48,7 +47,7 @@ The MIR-based region analysis consists of two major functions: ## Universal regions -The [`UnversalRegions`] type represents a collection of _universal_ regions +The [`UniversalRegions`] type represents a collection of _universal_ regions corresponding to some MIR `DefId`. It is constructed in [`replace_regions_in_mir`] when we replace all regions with fresh inference variables. [`UniversalRegions`] contains indices for all the free regions in @@ -71,6 +70,8 @@ TODO: write about _how_ these regions are computed. [`UniversalRegions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/universal_regions/struct.UniversalRegions.html + + ## Region variables The value of a region can be thought of as a **set**. This set contains all @@ -103,8 +104,10 @@ The kinds of region elements are as follows: ## Constraints -Before we can infer the value of regions, we need to collect constraints on the -regions. There are two primary types of constraints. +Before we can infer the value of regions, we need to collect +constraints on the regions. The full set of constraints is described +in [the section on constraint propagation][cp], but the two most +common sorts of constraints are: 1. Outlives constraints. These are constraints that one region outlives another (e.g. `'a: 'b`). Outlives constraints are generated by the [MIR type @@ -234,460 +237,3 @@ tests and universal regions, as discussed above. [`check_type_tests`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.check_type_tests [`check_universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.check_universal_regions -## Closures - -When we are checking the type tests and universal regions, we may come across a -constraint that we can't prove yet if we are in a closure body! However, the -necessary constraints may actually hold (we just don't know it yet). Thus, if -we are inside a closure, we just collect all the constraints we can't prove yet -and return them. Later, when we are borrow check the MIR node that created the -closure, we can also check that these constraints hold. At that time, if we -can't prove they hold, we report an error. - -## Placeholders and universes - -(This section describes ongoing work that hasn't landed yet.) - -From time to time we have to reason about regions that we can't -concretely know. For example, consider this program: - -```rust,ignore -// A function that needs a static reference -fn foo(x: &'static u32) { } - -fn bar(f: for<'a> fn(&'a u32)) { - // ^^^^^^^^^^^^^^^^^^^ a function that can accept **any** reference - let x = 22; - f(&x); -} - -fn main() { - bar(foo); -} -``` - -This program ought not to type-check: `foo` needs a static reference -for its argument, and `bar` wants to be given a function that that -accepts **any** reference (so it can call it with something on its -stack, for example). But *how* do we reject it and *why*? - -### Subtyping and Placeholders - -When we type-check `main`, and in particular the call `bar(foo)`, we -are going to wind up with a subtyping relationship like this one: - -```text -fn(&'static u32) <: for<'a> fn(&'a u32) ----------------- ------------------- -the type of `foo` the type `bar` expects -``` - -We handle this sort of subtyping by taking the variables that are -bound in the supertype and replacing them with -[universally quantified](../appendix/background.html#quantified) -representatives, written like `!1`. We call these regions "placeholder -regions" – they represent, basically, "some unknown region". - -Once we've done that replacement, we have the following relation: - -```text -fn(&'static u32) <: fn(&'!1 u32) -``` - -The key idea here is that this unknown region `'!1` is not related to -any other regions. So if we can prove that the subtyping relationship -is true for `'!1`, then it ought to be true for any region, which is -what we wanted. - -So let's work through what happens next. To check if two functions are -subtypes, we check if their arguments have the desired relationship -(fn arguments are [contravariant](../appendix/background.html#variance), so -we swap the left and right here): - -```text -&'!1 u32 <: &'static u32 -``` - -According to the basic subtyping rules for a reference, this will be -true if `'!1: 'static`. That is – if "some unknown region `!1`" lives -outlives `'static`. Now, this *might* be true – after all, `'!1` -could be `'static` – but we don't *know* that it's true. So this -should yield up an error (eventually). - -### What is a universe - -In the previous section, we introduced the idea of a placeholder -region, and we denoted it `!1`. We call this number `1` the **universe -index**. The idea of a "universe" is that it is a set of names that -are in scope within some type or at some point. Universes are formed -into a tree, where each child extends its parents with some new names. -So the **root universe** conceptually contains global names, such as -the the lifetime `'static` or the type `i32`. In the compiler, we also -put generic type parameters into this root universe (in this sense, -there is not just one root universe, but one per item). So consider -this function `bar`: - -```rust,ignore -struct Foo { } - -fn bar<'a, T>(t: &'a T) { - ... -} -``` - -Here, the root universe would consist of the lifetimes `'static` and -`'a`. In fact, although we're focused on lifetimes here, we can apply -the same concept to types, in which case the types `Foo` and `T` would -be in the root universe (along with other global types, like `i32`). -Basically, the root universe contains all the names that -[appear free](../appendix/background.html#free-vs-bound) in the body of `bar`. - -Now let's extend `bar` a bit by adding a variable `x`: - -```rust,ignore -fn bar<'a, T>(t: &'a T) { - let x: for<'b> fn(&'b u32) = ...; -} -``` - -Here, the name `'b` is not part of the root universe. Instead, when we -"enter" into this `for<'b>` (e.g., by replacing it with a placeholder), we will create -a child universe of the root, let's call it U1: - -```text -U0 (root universe) -│ -└─ U1 (child universe) -``` - -The idea is that this child universe U1 extends the root universe U0 -with a new name, which we are identifying by its universe number: -`!1`. - -Now let's extend `bar` a bit by adding one more variable, `y`: - -```rust,ignore -fn bar<'a, T>(t: &'a T) { - let x: for<'b> fn(&'b u32) = ...; - let y: for<'c> fn(&'b u32) = ...; -} -``` - -When we enter *this* type, we will again create a new universe, which -we'll call `U2`. Its parent will be the root universe, and U1 will be -its sibling: - -```text -U0 (root universe) -│ -├─ U1 (child universe) -│ -└─ U2 (child universe) -``` - -This implies that, while in U2, we can name things from U0 or U2, but -not U1. - -**Giving existential variables a universe.** Now that we have this -notion of universes, we can use it to extend our type-checker and -things to prevent illegal names from leaking out. The idea is that we -give each inference (existential) variable – whether it be a type or -a lifetime – a universe. That variable's value can then only -reference names visible from that universe. So for example is a -lifetime variable is created in U0, then it cannot be assigned a value -of `!1` or `!2`, because those names are not visible from the universe -U0. - -**Representing universes with just a counter.** You might be surprised -to see that the compiler doesn't keep track of a full tree of -universes. Instead, it just keeps a counter – and, to determine if -one universe can see another one, it just checks if the index is -greater. For example, U2 can see U0 because 2 >= 0. But U0 cannot see -U2, because 0 >= 2 is false. - -How can we get away with this? Doesn't this mean that we would allow -U2 to also see U1? The answer is that, yes, we would, **if that -question ever arose**. But because of the structure of our type -checker etc, there is no way for that to happen. In order for -something happening in the universe U1 to "communicate" with something -happening in U2, they would have to have a shared inference variable X -in common. And because everything in U1 is scoped to just U1 and its -children, that inference variable X would have to be in U0. And since -X is in U0, it cannot name anything from U1 (or U2). This is perhaps easiest -to see by using a kind of generic "logic" example: - -```text -exists { - forall { ... /* Y is in U1 ... */ } - forall { ... /* Z is in U2 ... */ } -} -``` - -Here, the only way for the two foralls to interact would be through X, -but neither Y nor Z are in scope when X is declared, so its value -cannot reference either of them. - -### Universes and placeholder region elements - -But where does that error come from? The way it happens is like this. -When we are constructing the region inference context, we can tell -from the type inference context how many placeholder variables exist -(the `InferCtxt` has an internal counter). For each of those, we -create a corresponding universal region variable `!n` and a "region -element" `placeholder(n)`. This corresponds to "some unknown set of other -elements". The value of `!n` is `{placeholder(n)}`. - -At the same time, we also give each existential variable a -**universe** (also taken from the `InferCtxt`). This universe -determines which placeholder elements may appear in its value: For -example, a variable in universe U3 may name `placeholder(1)`, `placeholder(2)`, and -`placeholder(3)`, but not `placeholder(4)`. Note that the universe of an inference -variable controls what region elements **can** appear in its value; it -does not say region elements **will** appear. - -### Placeholders and outlives constraints - -In the region inference engine, outlives constraints have the form: - -```text -V1: V2 @ P -``` - -where `V1` and `V2` are region indices, and hence map to some region -variable (which may be universally or existentially quantified). The -`P` here is a "point" in the control-flow graph; it's not important -for this section. This variable will have a universe, so let's call -those universes `U(V1)` and `U(V2)` respectively. (Actually, the only -one we are going to care about is `U(V1)`.) - -When we encounter this constraint, the ordinary procedure is to start -a DFS from `P`. We keep walking so long as the nodes we are walking -are present in `value(V2)` and we add those nodes to `value(V1)`. If -we reach a return point, we add in any `end(X)` elements. That part -remains unchanged. - -But then *after that* we want to iterate over the placeholder `placeholder(x)` -elements in V2 (each of those must be visible to `U(V2)`, but we -should be able to just assume that is true, we don't have to check -it). We have to ensure that `value(V1)` outlives each of those -placeholder elements. - -Now there are two ways that could happen. First, if `U(V1)` can see -the universe `x` (i.e., `x <= U(V1)`), then we can just add `placeholder(x)` -to `value(V1)` and be done. But if not, then we have to approximate: -we may not know what set of elements `placeholder(x)` represents, but we -should be able to compute some sort of **upper bound** B for it – -some region B that outlives `placeholder(x)`. For now, we'll just use -`'static` for that (since it outlives everything) – in the future, we -can sometimes be smarter here (and in fact we have code for doing this -already in other contexts). Moreover, since `'static` is in the root -universe U0, we know that all variables can see it – so basically if -we find that `value(V2)` contains `placeholder(x)` for some universe `x` -that `V1` can't see, then we force `V1` to `'static`. - -### Extending the "universal regions" check - -After all constraints have been propagated, the NLL region inference -has one final check, where it goes over the values that wound up being -computed for each universal region and checks that they did not get -'too large'. In our case, we will go through each placeholder region -and check that it contains *only* the `placeholder(u)` element it is known to -outlive. (Later, we might be able to know that there are relationships -between two placeholder regions and take those into account, as we do -for universal regions from the fn signature.) - -Put another way, the "universal regions" check can be considered to be -checking constraints like: - -```text -{placeholder(1)}: V1 -``` - -where `{placeholder(1)}` is like a constant set, and V1 is the variable we -made to represent the `!1` region. - -## Back to our example - -OK, so far so good. Now let's walk through what would happen with our -first example: - -```text -fn(&'static u32) <: fn(&'!1 u32) @ P // this point P is not imp't here -``` - -The region inference engine will create a region element domain like this: - -```text -{ CFG; end('static); placeholder(1) } - --- ------------ ------- from the universe `!1` - | 'static is always in scope - all points in the CFG; not especially relevant here -``` - -It will always create two universal variables, one representing -`'static` and one representing `'!1`. Let's call them Vs and V1. They -will have initial values like so: - -```text -Vs = { CFG; end('static) } // it is in U0, so can't name anything else -V1 = { placeholder(1) } -``` - -From the subtyping constraint above, we would have an outlives constraint like - -```text -'!1: 'static @ P -``` - -To process this, we would grow the value of V1 to include all of Vs: - -```text -Vs = { CFG; end('static) } -V1 = { CFG; end('static), placeholder(1) } -``` - -At that point, constraint propagation is complete, because all the -outlives relationships are satisfied. Then we would go to the "check -universal regions" portion of the code, which would test that no -universal region grew too large. - -In this case, `V1` *did* grow too large – it is not known to outlive -`end('static)`, nor any of the CFG – so we would report an error. - -## Another example - -What about this subtyping relationship? - -```text -for<'a> fn(&'a u32, &'a u32) - <: -for<'b, 'c> fn(&'b u32, &'c u32) -``` - -Here we would replace the bound region in the supertype with a placeholder, as before, yielding: - -```text -for<'a> fn(&'a u32, &'a u32) - <: -fn(&'!1 u32, &'!2 u32) -``` - -then we instantiate the variable on the left-hand side with an -existential in universe U2, yielding the following (`?n` is a notation -for an existential variable): - -```text -fn(&'?3 u32, &'?3 u32) - <: -fn(&'!1 u32, &'!2 u32) -``` - -Then we break this down further: - -```text -&'!1 u32 <: &'?3 u32 -&'!2 u32 <: &'?3 u32 -``` - -and even further, yield up our region constraints: - -```text -'!1: '?3 -'!2: '?3 -``` - -Note that, in this case, both `'!1` and `'!2` have to outlive the -variable `'?3`, but the variable `'?3` is not forced to outlive -anything else. Therefore, it simply starts and ends as the empty set -of elements, and hence the type-check succeeds here. - -(This should surprise you a little. It surprised me when I first realized it. -We are saying that if we are a fn that **needs both of its arguments to have -the same region**, we can accept being called with **arguments with two -distinct regions**. That seems intuitively unsound. But in fact, it's fine, as -I tried to explain in [this issue][ohdeargoditsallbroken] on the Rust issue -tracker long ago. The reason is that even if we get called with arguments of -two distinct lifetimes, those two lifetimes have some intersection (the call -itself), and that intersection can be our value of `'a` that we use as the -common lifetime of our arguments. -nmatsakis) - -[ohdeargoditsallbroken]: https://github.com/rust-lang/rust/issues/32330#issuecomment-202536977 - -## Final example - -Let's look at one last example. We'll extend the previous one to have -a return type: - -```text -for<'a> fn(&'a u32, &'a u32) -> &'a u32 - <: -for<'b, 'c> fn(&'b u32, &'c u32) -> &'b u32 -``` - -Despite seeming very similar to the previous example, this case is going to get -an error. That's good: the problem is that we've gone from a fn that promises -to return one of its two arguments, to a fn that is promising to return the -first one. That is unsound. Let's see how it plays out. - -First, we replace the bound region in the supertype with a placeholder: - -```text -for<'a> fn(&'a u32, &'a u32) -> &'a u32 - <: -fn(&'!1 u32, &'!2 u32) -> &'!1 u32 -``` - -Then we instantiate the subtype with existentials (in U2): - -```text -fn(&'?3 u32, &'?3 u32) -> &'?3 u32 - <: -fn(&'!1 u32, &'!2 u32) -> &'!1 u32 -``` - -And now we create the subtyping relationships: - -```text -&'!1 u32 <: &'?3 u32 // arg 1 -&'!2 u32 <: &'?3 u32 // arg 2 -&'?3 u32 <: &'!1 u32 // return type -``` - -And finally the outlives relationships. Here, let V1, V2, and V3 be the -variables we assign to `!1`, `!2`, and `?3` respectively: - -```text -V1: V3 -V2: V3 -V3: V1 -``` - -Those variables will have these initial values: - -```text -V1 in U1 = {placeholder(1)} -V2 in U2 = {placeholder(2)} -V3 in U2 = {} -``` - -Now because of the `V3: V1` constraint, we have to add `placeholder(1)` into `V3` (and -indeed it is visible from `V3`), so we get: - -```text -V3 in U2 = {placeholder(1)} -``` - -then we have this constraint `V2: V3`, so we wind up having to enlarge -`V2` to include `placeholder(1)` (which it can also see): - -```text -V2 in U2 = {placeholder(1), placeholder(2)} -``` - -Now constraint propagation is done, but when we check the outlives -relationships, we find that `V2` includes this new element `placeholder(1)`, -so we report an error. - -## Borrow Checker Errors - -TODO: we should discuss how to generate errors from the results of these analyses. diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference/closure_constraints.md b/src/doc/rustc-guide/src/borrow_check/region_inference/closure_constraints.md new file mode 100644 index 0000000000..13230d037c --- /dev/null +++ b/src/doc/rustc-guide/src/borrow_check/region_inference/closure_constraints.md @@ -0,0 +1,10 @@ +# Propagating closure constraints + +When we are checking the type tests and universal regions, we may come +across a constraint that we can't prove yet if we are in a closure +body! However, the necessary constraints may actually hold (we just +don't know it yet). Thus, if we are inside a closure, we just collect +all the constraints we can't prove yet and return them. Later, when we +are borrow check the MIR node that created the closure, we can also +check that these constraints hold. At that time, if we can't prove +they hold, we report an error. diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference/constraint_propagation.md b/src/doc/rustc-guide/src/borrow_check/region_inference/constraint_propagation.md new file mode 100644 index 0000000000..7b9eeb13d4 --- /dev/null +++ b/src/doc/rustc-guide/src/borrow_check/region_inference/constraint_propagation.md @@ -0,0 +1,224 @@ +# Constraint propagation + +The main work of the region inference is **constraint propagation**, +which is done in the [`propagate_constraints`] function. There are +three sorts of constraints that are used in NLL, and we'll explain how +`propagate_constraints` works by "layering" those sorts of constraints +on one at a time (each of them is fairly independent from the others): + +- liveness constraints (`R live at E`), which arise from liveness; +- outlives constraints (`R1: R2`), which arise from subtyping; +- [member constraints][m_c] (`member R_m of [R_c...]`), which arise from impl Trait. + +[`propagate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints +[m_c]: ./member_constraints.html + +In this chapter, we'll explain the "heart" of constraint propagation, +covering both liveness and outlives constraints. + +## Notation and high-level concepts + +Conceptually, region inference is a "fixed-point" computation. It is +given some set of constraints `{C}` and it computes a set of values +`Values: R -> {E}` that maps each region `R` to a set of elements +`{E}` (see [here][riv] for more notes on region elements): + +- Initially, each region is mapped to an empty set, so `Values(R) = + {}` for all regions `R`. +- Next, we process the constraints repeatedly until a fixed-point is reached: + - For each constraint C: + - Update `Values` as needed to satisfy the constraint + +[riv]: ../region-inference.html#region-variables + +As a simple example, if we have a liveness constraint `R live at E`, +then we can apply `Values(R) = Values(R) union {E}` to make the +constraint be satisfied. Similarly, if we have an outlives constraints +`R1: R2`, we can apply `Values(R1) = Values(R1) union Values(R2)`. +(Member constraints are more complex and we discuss them [in this section][m_c].) + +In practice, however, we are a bit more clever. Instead of applying +the constraints in a loop, we can analyze the constraints and figure +out the correct order to apply them, so that we only have to apply +each constraint once in order to find the final result. + +Similarly, in the implementation, the `Values` set is stored in the +`scc_values` field, but they are indexed not by a *region* but by a +*strongly connected component* (SCC). SCCs are an optimization that +avoids a lot of redundant storage and computation. They are explained +in the section on outlives constraints. + +## Liveness constraints + +A **liveness constraint** arises when some variable whose type +includes a region R is live at some [point] P. This simply means that +the value of R must include the point P. Liveness constraints are +computed by the MIR type checker. + +[point]: ../../appendix/glossary.html + +A liveness constraint `R live at E` is satisfied if `E` is a member of +`Values(R)`. So to "apply" such a constraint to `Values`, we just have +to compute `Values(R) = Values(R) union {E}`. + +The liveness values are computed in the type-check and passed to the +region inference upon creation in the `liveness_constraints` argument. +These are not represented as individual constraints like `R live at E` +though; instead, we store a (sparse) bitset per region variable (of +type [`LivenessValues`]). This way we only need a single bit for each +liveness constraint. + +[`liveness_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.liveness_constraints +[`LivenessValues`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/values/struct.LivenessValues.html + +One thing that is worth mentioning: All lifetime parameters are always +considered to be live over the entire function body. This is because +they correspond to some portion of the *caller's* execution, and that +execution clearly includes the time spent in this function, since the +caller is waiting for us to return. + +## Outlives constraints + +An outlives constraint `'a: 'b` indicates that the value of `'a` must +be a **superset** of the value of `'b`. That is, an outlives +constraint `R1: R2` is satisfied if `Values(R1)` is a superset of +`Values(R2)`. So to "apply" such a constraint to `Values`, we just +have to compute `Values(R1) = Values(R1) union Values(R2)`. + +One observation that follows from this is that if you have `R1: R2` +and `R2: R1`, then `R1 = R2` must be true. Similarly, if you have: + +``` +R1: R2 +R2: R3 +R3: R4 +R4: R1 +``` + +then `R1 = R2 = R3 = R4` follows. We take advantage of this to make things +much faster, as described shortly. + +In the code, the set of outlives constraints is given to the region +inference context on creation in a parameter of type +[`ConstraintSet`]. The constraint set is basically just a list of `'a: +'b` constraints. + +### The outlives constraint graph and SCCs + +In order to work more efficiently with outlives constraints, they are +[converted into the form of a graph][graph-fn], where the nodes of the +graph are region variables (`'a`, `'b`) and each constraint `'a: 'b` +induces an edge `'a -> 'b`. This conversion happens in the +[`RegionInferenceContext::new`] function that creates the inference +context. + +[`ConstraintSet`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/constraints/struct.ConstraintSet.html +[graph-fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/constraints/struct.ConstraintSet.html#method.graph +[`RegionInferenceContext::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.new + +When using a graph representation, we can detect regions that must be equal +by looking for cycles. That is, if you have a constraint like + +``` +'a: 'b +'b: 'c +'c: 'd +'d: 'a +``` + +then this will correspond to a cycle in the graph containing the +elements `'a...'d`. + +Therefore, one of the first things that we do in propagating region +values is to compute the **strongly connected components** (SCCs) in +the constraint graph. The result is stored in the [`constraint_sccs`] +field. You can then easily find the SCC that a region `r` is a part of +by invoking `constraint_sccs.scc(r)`. + +Working in terms of SCCs allows us to be more efficient: if we have a +set of regions `'a...'d` that are part of a single SCC, we don't have +to compute/store their values separarely. We can just store one value +**for the SCC**, since they must all be equal. + +If you look over the region inference code, you will see that a number +of fields are defined in terms of SCCs. For example, the +[`scc_values`] field stores the values of each SCC. To get the value +of a specific region `'a` then, we first figure out the SCC that the +region is a part of, and then find the value of that SCC. + +[`constraint_sccs`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.constraint_sccs +[`scc_values`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#structfield.scc_values + +When we compute SCCs, we not only figure out which regions are a +member of each SCC, we also figure out the edges between them. So for example +consider this set of outlives constraints: + +``` +'a: 'b +'b: 'a + +'a: 'c + +'c: 'd +'d: 'c +``` + +Here we have two SCCs: S0 contains `'a` and `'b`, and S1 contains `'c` +and `'d`. But these SCCs are not independent: because `'a: 'c`, that +means that `S0: S1` as well. That is -- the value of `S0` must be a +superset of the value of `S1`. One crucial thing is that this graph of +SCCs is always a DAG -- that is, it never has cycles. This is because +all the cycles have been removed to form the SCCs themselves. + +### Applying liveness constraints to SCCs + +The liveness constraints that come in from the type-checker are +expressed in terms of regions -- that is, we have a map like +`Liveness: R -> {E}`. But we want our final result to be expressed +in terms of SCCs -- we can integrate these liveness constraints very +easily just by taking the union: + +``` +for each region R: + let S be the SCC that contains R + Values(S) = Values(S) union Liveness(R) +``` + +In the region inferencer, this step is done in [`RegionInferenceContext::new`]. + +### Applying outlives constraints + +Once we have computed the DAG of SCCs, we use that to structure out +entire computation. If we have an edge `S1 -> S2` between two SCCs, +that means that `Values(S1) >= Values(S2)` must hold. So, to compute +the value of `S1`, we first compute the values of each successor `S2`. +Then we simply union all of those values together. To use a +quasi-iterator-like notation: + +``` +Values(S1) = + s1.successors() + .map(|s2| Values(s2)) + .union() +``` + +In the code, this work starts in the [`propagate_constraints`] +function, which iterates over all the SCCs. For each SCC `S1`, we +compute its value by first computing the value of its +successors. Since SCCs form a DAG, we don't have to be concerned about +cycles, though we do need to keep a set around to track whether we +have already processed a given SCC or not. For each successor `S2`, once +we have computed `S2`'s value, we can union those elements into the +value for `S1`. (Although we have to be careful in this process to +properly handle [higher-ranked +placeholders](./placeholders_and_universes.html). Note that the value +for `S1` already contains the liveness constraints, since they were +added in [`RegionInferenceContext::new`]. + +Once that process is done, we now have the "minimal value" for `S1`, +taking into account all of the liveness and outlives +constraints. However, in order to complete the process, we must also +consider [member constraints][m_c], which are described in [a later +section][m_c]. + + diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference/error_reporting.md b/src/doc/rustc-guide/src/borrow_check/region_inference/error_reporting.md new file mode 100644 index 0000000000..79b3e077c7 --- /dev/null +++ b/src/doc/rustc-guide/src/borrow_check/region_inference/error_reporting.md @@ -0,0 +1,3 @@ +# Reporting region errors + +TODO: we should discuss how to generate errors from the results of these analyses. diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference/lifetime_parameters.md b/src/doc/rustc-guide/src/borrow_check/region_inference/lifetime_parameters.md new file mode 100644 index 0000000000..ecd3a19a5b --- /dev/null +++ b/src/doc/rustc-guide/src/borrow_check/region_inference/lifetime_parameters.md @@ -0,0 +1,125 @@ +# Universal regions + +"Universal regions" is the name that the code uses to refer to "named +lifetimes" -- e.g., lifetime parameters and `'static`. The name +derives from the fact that such lifetimes are "universally quantified" +(i.e., we must make sure the code is true for all values of those +lifetimes). It is worth spending a bit of discussing how lifetime +parameters are handled during region inference. Consider this example: + +```rust +fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { + x +} +``` + +This example is intended not to compile, because we are returning `x`, +which has type `&'a u32`, but our signature promises that we will +return a `&'b u32` value. But how are lifetimes like `'a` and `'b` +integrated into region inference, and how this error wind up being +detected? + +## Universal regions and their relationships to one another + +Early on in region inference, one of the first things we do is to +construct a [`UniversalRegions`] struct. This struct tracks the +various universal regions in scope on a particular function. We also +create a [`UniversalRegionRelations`] struct, which tracks their +relationships to one another. So if you have e.g. `where 'a: 'b`, then +the [`UniversalRegionRelations`] struct would track that `'a: 'b` is +known to hold (which could be tested with the [`outlives`] function. + +[`UniversalRegions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/universal_regions/struct.UniversalRegions.html +[`UniversalRegionRelations`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/type_check/free_region_relations/struct.UniversalRegionRelations.html +[`outlives`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/type_check/free_region_relations/struct.UniversalRegionRelations.html#method.outlives + +## Everything is a region variable + +One important aspect of how NLL region inference works is that **all +lifetimes** are represented as numbered variables. This means that the +only variant of [`ty::RegionKind`] that we use is the [`ReVar`] +variant. These region variables are broken into two major categories, +based on their index: + +[`ty::RegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/enum.RegionKind.html +[`ReVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/enum.RegionKind.html#variant.ReVar + +- 0..N: universal regions -- the ones we are discussing here. In this + case, the code must be correct with respect to any value of those + variables that meets the declared relationships. +- N..M: existential regions -- inference variables where the region + inferencer is tasked with finding *some* suitable value. + +In fact, the universal regions can be further subdivided based on +where they were brought into scope (see the [`RegionClassification`] +type). These subdivions are not important for the topics discussed +here, but become important when we consider [closure constraint +propagation](./closure_constraints.html), so we discuss them there. + +[`RegionClassification`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/universal_regions/enum.RegionClassification.html#variant.Local + +## Universal lifetimes as the elements of a region's value + +As noted previously, the value that we infer for each region is a set +`{E}`. The elements of this set can be points in the control-flow +graph, but they can also be an element `end('a)` corresponding to each +universal lifetime `'a`. If the value for some region `R0` includes +`end('a`), then this implies that `R0` must extend until the end of `'a` +in the caller. + +## The "value" of a universal region + +During region inference, we compute a value for each universal region +in the same way as we compute values for other regions. This value +represents, effectively, the **lower bound** on that universal region +-- the things that it must outlive. We now describe how we use this +value to check for errors. + +## Liveness and universal regions + +All universal regions have an initial liveness constraint that +includes the entire function body. This is because lifetime parameters +are defined in the caller and must include the entirety of the +function call that invokes this particular function. In addition, each +universal region `'a` includes itself (that is, `end('a)`) in its +liveness constraint (i.e., `'a` must extend until the end of +itself). In the code, these liveness constraints are setup in +[`init_free_and_bound_regions`]. + +[`init_free_and_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.init_free_and_bound_regions + +## Propagating outlives constraints for universal regions + +So, consider the first example of this section: + +```rust +fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { + x +} +``` + +Here, returning `x` requires that `&'a u32 <: &'b u32`, which gives +rise to an outlives constraint `'a: 'b`. Combined with our default liveness +constraints we get: + +``` +'a live at {B, end('a)} // B represents the "function body" +'b live at {B, end('b)} +'a: 'b +``` + +When we process the `'a: 'b` constraint, therefore, we will add +`end('b)` into the value for `'a`, resulting in a final value of `{B, +end('a), end('b)}`. + +## Detecting errors + +Once we have finished constraint propagation, we then enforce a +constraint that if some universal region `'a` includes an element +`end('b)`, then `'a: 'b` must be declared in the function's bounds. If +not, as in our example, that is an error. This check is done in the +[`check_universal_regions`] function, which simply iterates over all +universal regions, inspects their final value, and tests against the +declared [`UniversalRegionRelations`]. + +[`check_universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.check_universal_regions diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md b/src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md new file mode 100644 index 0000000000..3f934e8642 --- /dev/null +++ b/src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md @@ -0,0 +1,193 @@ +# Member constraints + +A member constraint `'m member of ['c_1..'c_N]` expresses that the +region `'m` must be *equal* to some **choice regions** `'c_i` (for +some `i`). These constraints cannot be expressed by users, but they +arise from `impl Trait` due to its lifetime capture rules. Consider a +function such as the following: + +```rust +fn make(a: &'a u32, b: &'b u32) -> impl Trait<'a, 'b> { .. } +``` + +Here, the true return type (often called the "hidden type") is only +permitted to capture the lifetimes `'a` or `'b`. You can kind of see +this more clearly by desugaring that `impl Trait` return type into its +more explicit form: + +```rust +type MakeReturn<'x, 'y> = impl Trait<'x, 'y>; +fn make(a: &'a u32, b: &'b u32) -> MakeReturn<'a, 'b> { .. } +``` + +Here, the idea is that the hidden type must be some type that could +have been written in place of the `impl Trait<'x, 'y>` -- but clearly +such a type can only reference the regions `'x` or `'y` (or +`'static`!), as those are the only names in scope. This limitation is +then translated into a restriction to only access `'a` or `'b` because +we are returning `MakeReturn<'a, 'b>`, where `'x` and `'y` have been +replaced with `'a` and `'b` respectively. + +## Detailed example + +To help us explain member constraints in more detail, let's spell out +the `make` example in a bit more detail. First off, let's assume that +you have some dummy trait: + +```rust +trait Trait<'a, 'b> { } +impl Trait<'_, '_> for T { } +``` + +and this is the `make` function (in desugared form): + +```rust +type MakeReturn<'x, 'y> = impl Trait<'x, 'y>; +fn make(a: &'a u32, b: &'b u32) -> MakeReturn<'a, 'b> { + (a, b) +} +``` + +What happens in this case is that the return type will be `(&'0 u32, &'1 u32)`, +where `'0` and `'1` are fresh region variables. We will have the following +region constraints: + +``` +'0 live at {L} +'1 live at {L} +'a: '0 +'b: '1 +'0 member of ['a, 'b, 'static] +'1 member of ['a, 'b, 'static] +``` + +Here the "liveness set" `{L}` corresponds to that subset of the body +where `'0` and `'1` are live -- basically the point from where the +return tuple is constructed to where it is returned (in fact, `'0` and +`'1` might have slightly different liveness sets, but that's not very +interesting to the point we are illustrating here). + +The `'a: '0` and `'b: '1` constraints arise from subtyping. When we +construct the `(a, b)` value, it will be assigned type `(&'0 u32, &'1 +u32)` -- the region variables reflect that the lifetimes of these +references could be made smaller. For this value to be created from +`a` and `b`, however, we do require that: + +``` +(&'a u32, &'b u32) <: (&'0 u32, &'1 u32) +``` + +which means in turn that `&'a u32 <: &'0 u32` and hence that `'a: '0` +(and similarly that `&'b u32 <: &'1 u32`, `'b: '1`). + +Note that if we ignore member constraints, the value of `'0` would be +inferred to some subset of the function body (from the liveness +constraints, which we did not write explicitly). It would never become +`'a`, because there is no need for it too -- we have a constraint that +`'a: '0`, but that just puts a "cap" on how *large* `'0` can grow to +become. Since we compute the *minimal* value that we can, we are happy +to leave `'0` as being just equal to the liveness set. This is where +member constraints come in. + +## Choices are always lifetime parameters + +At present, the "choice" regions from a member constraint are always +lifetime parameters from the current function. This falls out from the +placement of impl Trait, though in the future it may not be the case. +We take some advantage of this fact, as it simplifies the current +code. In particular, we don't have to consider a case like `'0 member +of ['1, 'static]`, in which the value of both `'0` and `'1` are being +inferred and hence changing. See [rust-lang/rust#61773] for more +information. + +[#61773]: https://github.com/rust-lang/rust/issues/61773 + +## Applying member constraints + +Member constraints are a bit more complex than other forms of +constraints. This is because they have a "or" quality to them -- that +is, they describe multiple choices that we must select from. E.g., in +our example constraint `'0 member of ['a, 'b, 'static]`, it might be +that `'0` is equal to `'a`, `'b`, *or* `'static`. How can we pick the +correct one? What we currently do is to look for a *minimal choice* +-- if we find one, then we will grow `'0` to be equal to that minimal +choice. To find that minimal choice, we take two factors into +consideration: lower and upper bounds. + +### Lower bounds + +The *lower bounds* are those lifetimes that `'0` *must outlive* -- +i.e., that `'0` must be larger than. In fact, when it comes time to +apply member constraints, we've already *computed* the lower bounds of +`'0` because we computed its minimal value (or at least, the lower +bounds considering everything but member constraints). + +Let `LB` be the current value of `'0`. We know then that `'0: LB` must +hold, whatever the final value of `'0` is. Therefore, we can rule out +any choice `'choice` where `'choice: LB` does not hold. + +Unfortunately, in our example, this is not very helpful. The lower +bound for `'0` will just be the liveness set `{L}`, and we know that +all the lifetime parameters outlive that set. So we are left with the +same set of choices here. (But in other examples, particularly those +with different variance, lower bound constraints may be relevant.) + +### Upper bounds + +The *upper bounds* are those lifetimes that *must outlive* `'0` -- +i.e., that `'0` must be *smaller* than. In our example, this would be +`'a`, because we have the constraint that `'a: '0`. In more complex +examples, the chain may be more indirect. + +We can use upper bounds to rule out members in a very similar way to +lower lower bounds. If UB is some upper bound, then we know that `UB: +'0` must hold, so we can rule out any choice `'choice` where `UB: +'choice` does not hold. + +In our example, we would be able to reduce our choice set from `['a, +'b, 'static]` to just `['a]`. This is because `'0` has an upper bound +of `'a`, and neither `'a: 'b` nor `'a: 'static` is known to hold. + +(For notes on how we collect upper bounds in the implementation, see +[the section below](#collecting).) + +### Minimal choice + +After applying lower and upper bounds, we can still sometimes have +multiple possibilities. For example, imagine a variant of our example +using types with the opposite variance. In that case, we would have +the constraint `'0: 'a` instead of `'a: '0`. Hence the current value +of `'0` would be `{L, 'a}`. Using this as a lower bound, we would be +able to narrow down the member choices to `['a, 'static]` because `'b: +'a` is not known to hold (but `'a: 'a` and `'static: 'a` do hold). We +would not have any upper bounds, so that would be our final set of choices. + +In that case, we apply the **minimal choice** rule -- basically, if +one of our choices if smaller than the others, we can use that. In +this case, we would opt for `'a` (and not `'static`). + +This choice is consistent with the general 'flow' of region +propagation, which always aims to compute a minimal value for the +region being inferred. However, it is somewhat arbitrary. + + + +### Collecting upper bounds in the implementation + +In practice, computing upper bounds is a bit inconvenient, because our +data structures are setup for the opposite. What we do is to compute +the **reverse SCC graph** (we do this lazilly and cache the result) -- +that is, a graph where `'a: 'b` induces an edge `SCC('b) -> +SCC('a)`. Like the normal SCC graph, this is a DAG. We can then do a +depth-first search starting from `SCC('0)` in this graph. This will +take us to all the SCCs that must outlive `'0`. + +One wrinkle is that, as we walk the "upper bound" SCCs, their values +will not yet have been fully computed. However, we **have** already +applied their liveness constraints, so we have some information about +their value. In particular, for any regions representing lifetime +parameters, their value will contain themselves (i.e., the initial +value for `'a` includes `'a` and the value for `'b` contains `'b`). So +we can collect all of the lifetime parameters that are reachable, +which is precisely what we are interested in. + diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference/placeholders_and_universes.md b/src/doc/rustc-guide/src/borrow_check/region_inference/placeholders_and_universes.md new file mode 100644 index 0000000000..e40ee11b19 --- /dev/null +++ b/src/doc/rustc-guide/src/borrow_check/region_inference/placeholders_and_universes.md @@ -0,0 +1,441 @@ +# Placeholders and universes + +From time to time we have to reason about regions that we can't +concretely know. For example, consider this program: + +```rust,ignore +// A function that needs a static reference +fn foo(x: &'static u32) { } + +fn bar(f: for<'a> fn(&'a u32)) { + // ^^^^^^^^^^^^^^^^^^^ a function that can accept **any** reference + let x = 22; + f(&x); +} + +fn main() { + bar(foo); +} +``` + +This program ought not to type-check: `foo` needs a static reference +for its argument, and `bar` wants to be given a function that that +accepts **any** reference (so it can call it with something on its +stack, for example). But *how* do we reject it and *why*? + +## Subtyping and Placeholders + +When we type-check `main`, and in particular the call `bar(foo)`, we +are going to wind up with a subtyping relationship like this one: + +```text +fn(&'static u32) <: for<'a> fn(&'a u32) +---------------- ------------------- +the type of `foo` the type `bar` expects +``` + +We handle this sort of subtyping by taking the variables that are +bound in the supertype and replacing them with +[universally quantified](../appendix/background.html#quantified) +representatives, denoted like `!1` here. We call these regions "placeholder +regions" – they represent, basically, "some unknown region". + +Once we've done that replacement, we have the following relation: + +```text +fn(&'static u32) <: fn(&'!1 u32) +``` + +The key idea here is that this unknown region `'!1` is not related to +any other regions. So if we can prove that the subtyping relationship +is true for `'!1`, then it ought to be true for any region, which is +what we wanted. + +So let's work through what happens next. To check if two functions are +subtypes, we check if their arguments have the desired relationship +(fn arguments are [contravariant](../appendix/background.html#variance), so +we swap the left and right here): + +```text +&'!1 u32 <: &'static u32 +``` + +According to the basic subtyping rules for a reference, this will be +true if `'!1: 'static`. That is – if "some unknown region `!1`" lives +outlives `'static`. Now, this *might* be true – after all, `'!1` +could be `'static` – but we don't *know* that it's true. So this +should yield up an error (eventually). + +## What is a universe? + +In the previous section, we introduced the idea of a placeholder +region, and we denoted it `!1`. We call this number `1` the **universe +index**. The idea of a "universe" is that it is a set of names that +are in scope within some type or at some point. Universes are formed +into a tree, where each child extends its parents with some new names. +So the **root universe** conceptually contains global names, such as +the the lifetime `'static` or the type `i32`. In the compiler, we also +put generic type parameters into this root universe (in this sense, +there is not just one root universe, but one per item). So consider +this function `bar`: + +```rust,ignore +struct Foo { } + +fn bar<'a, T>(t: &'a T) { + ... +} +``` + +Here, the root universe would consist of the lifetimes `'static` and +`'a`. In fact, although we're focused on lifetimes here, we can apply +the same concept to types, in which case the types `Foo` and `T` would +be in the root universe (along with other global types, like `i32`). +Basically, the root universe contains all the names that +[appear free](../appendix/background.html#free-vs-bound) in the body of `bar`. + +Now let's extend `bar` a bit by adding a variable `x`: + +```rust,ignore +fn bar<'a, T>(t: &'a T) { + let x: for<'b> fn(&'b u32) = ...; +} +``` + +Here, the name `'b` is not part of the root universe. Instead, when we +"enter" into this `for<'b>` (e.g., by replacing it with a placeholder), we will create +a child universe of the root, let's call it U1: + +```text +U0 (root universe) +│ +└─ U1 (child universe) +``` + +The idea is that this child universe U1 extends the root universe U0 +with a new name, which we are identifying by its universe number: +`!1`. + +Now let's extend `bar` a bit by adding one more variable, `y`: + +```rust,ignore +fn bar<'a, T>(t: &'a T) { + let x: for<'b> fn(&'b u32) = ...; + let y: for<'c> fn(&'b u32) = ...; +} +``` + +When we enter *this* type, we will again create a new universe, which +we'll call `U2`. Its parent will be the root universe, and U1 will be +its sibling: + +```text +U0 (root universe) +│ +├─ U1 (child universe) +│ +└─ U2 (child universe) +``` + +This implies that, while in U2, we can name things from U0 or U2, but +not U1. + +**Giving existential variables a universe.** Now that we have this +notion of universes, we can use it to extend our type-checker and +things to prevent illegal names from leaking out. The idea is that we +give each inference (existential) variable – whether it be a type or +a lifetime – a universe. That variable's value can then only +reference names visible from that universe. So for example if a +lifetime variable is created in U0, then it cannot be assigned a value +of `!1` or `!2`, because those names are not visible from the universe +U0. + +**Representing universes with just a counter.** You might be surprised +to see that the compiler doesn't keep track of a full tree of +universes. Instead, it just keeps a counter – and, to determine if +one universe can see another one, it just checks if the index is +greater. For example, U2 can see U0 because 2 >= 0. But U0 cannot see +U2, because 0 >= 2 is false. + +How can we get away with this? Doesn't this mean that we would allow +U2 to also see U1? The answer is that, yes, we would, **if that +question ever arose**. But because of the structure of our type +checker etc, there is no way for that to happen. In order for +something happening in the universe U1 to "communicate" with something +happening in U2, they would have to have a shared inference variable X +in common. And because everything in U1 is scoped to just U1 and its +children, that inference variable X would have to be in U0. And since +X is in U0, it cannot name anything from U1 (or U2). This is perhaps easiest +to see by using a kind of generic "logic" example: + +```text +exists { + forall { ... /* Y is in U1 ... */ } + forall { ... /* Z is in U2 ... */ } +} +``` + +Here, the only way for the two foralls to interact would be through X, +but neither Y nor Z are in scope when X is declared, so its value +cannot reference either of them. + +## Universes and placeholder region elements + +But where does that error come from? The way it happens is like this. +When we are constructing the region inference context, we can tell +from the type inference context how many placeholder variables exist +(the `InferCtxt` has an internal counter). For each of those, we +create a corresponding universal region variable `!n` and a "region +element" `placeholder(n)`. This corresponds to "some unknown set of other +elements". The value of `!n` is `{placeholder(n)}`. + +At the same time, we also give each existential variable a +**universe** (also taken from the `InferCtxt`). This universe +determines which placeholder elements may appear in its value: For +example, a variable in universe U3 may name `placeholder(1)`, `placeholder(2)`, and +`placeholder(3)`, but not `placeholder(4)`. Note that the universe of an inference +variable controls what region elements **can** appear in its value; it +does not say region elements **will** appear. + +## Placeholders and outlives constraints + +In the region inference engine, outlives constraints have the form: + +```text +V1: V2 @ P +``` + +where `V1` and `V2` are region indices, and hence map to some region +variable (which may be universally or existentially quantified). The +`P` here is a "point" in the control-flow graph; it's not important +for this section. This variable will have a universe, so let's call +those universes `U(V1)` and `U(V2)` respectively. (Actually, the only +one we are going to care about is `U(V1)`.) + +When we encounter this constraint, the ordinary procedure is to start +a DFS from `P`. We keep walking so long as the nodes we are walking +are present in `value(V2)` and we add those nodes to `value(V1)`. If +we reach a return point, we add in any `end(X)` elements. That part +remains unchanged. + +But then *after that* we want to iterate over the placeholder `placeholder(x)` +elements in V2 (each of those must be visible to `U(V2)`, but we +should be able to just assume that is true, we don't have to check +it). We have to ensure that `value(V1)` outlives each of those +placeholder elements. + +Now there are two ways that could happen. First, if `U(V1)` can see +the universe `x` (i.e., `x <= U(V1)`), then we can just add `placeholder(x)` +to `value(V1)` and be done. But if not, then we have to approximate: +we may not know what set of elements `placeholder(x)` represents, but we +should be able to compute some sort of **upper bound** B for it – +some region B that outlives `placeholder(x)`. For now, we'll just use +`'static` for that (since it outlives everything) – in the future, we +can sometimes be smarter here (and in fact we have code for doing this +already in other contexts). Moreover, since `'static` is in the root +universe U0, we know that all variables can see it – so basically if +we find that `value(V2)` contains `placeholder(x)` for some universe `x` +that `V1` can't see, then we force `V1` to `'static`. + +## Extending the "universal regions" check + +After all constraints have been propagated, the NLL region inference +has one final check, where it goes over the values that wound up being +computed for each universal region and checks that they did not get +'too large'. In our case, we will go through each placeholder region +and check that it contains *only* the `placeholder(u)` element it is known to +outlive. (Later, we might be able to know that there are relationships +between two placeholder regions and take those into account, as we do +for universal regions from the fn signature.) + +Put another way, the "universal regions" check can be considered to be +checking constraints like: + +```text +{placeholder(1)}: V1 +``` + +where `{placeholder(1)}` is like a constant set, and V1 is the variable we +made to represent the `!1` region. + +## Back to our example + +OK, so far so good. Now let's walk through what would happen with our +first example: + +```text +fn(&'static u32) <: fn(&'!1 u32) @ P // this point P is not imp't here +``` + +The region inference engine will create a region element domain like this: + +```text +{ CFG; end('static); placeholder(1) } + --- ------------ ------- from the universe `!1` + | 'static is always in scope + all points in the CFG; not especially relevant here +``` + +It will always create two universal variables, one representing +`'static` and one representing `'!1`. Let's call them Vs and V1. They +will have initial values like so: + +```text +Vs = { CFG; end('static) } // it is in U0, so can't name anything else +V1 = { placeholder(1) } +``` + +From the subtyping constraint above, we would have an outlives constraint like + +```text +'!1: 'static @ P +``` + +To process this, we would grow the value of V1 to include all of Vs: + +```text +Vs = { CFG; end('static) } +V1 = { CFG; end('static), placeholder(1) } +``` + +At that point, constraint propagation is complete, because all the +outlives relationships are satisfied. Then we would go to the "check +universal regions" portion of the code, which would test that no +universal region grew too large. + +In this case, `V1` *did* grow too large – it is not known to outlive +`end('static)`, nor any of the CFG – so we would report an error. + +## Another example + +What about this subtyping relationship? + +```text +for<'a> fn(&'a u32, &'a u32) + <: +for<'b, 'c> fn(&'b u32, &'c u32) +``` + +Here we would replace the bound region in the supertype with a placeholder, as before, yielding: + +```text +for<'a> fn(&'a u32, &'a u32) + <: +fn(&'!1 u32, &'!2 u32) +``` + +then we instantiate the variable on the left-hand side with an +existential in universe U2, yielding the following (`?n` is a notation +for an existential variable): + +```text +fn(&'?3 u32, &'?3 u32) + <: +fn(&'!1 u32, &'!2 u32) +``` + +Then we break this down further: + +```text +&'!1 u32 <: &'?3 u32 +&'!2 u32 <: &'?3 u32 +``` + +and even further, yield up our region constraints: + +```text +'!1: '?3 +'!2: '?3 +``` + +Note that, in this case, both `'!1` and `'!2` have to outlive the +variable `'?3`, but the variable `'?3` is not forced to outlive +anything else. Therefore, it simply starts and ends as the empty set +of elements, and hence the type-check succeeds here. + +(This should surprise you a little. It surprised me when I first realized it. +We are saying that if we are a fn that **needs both of its arguments to have +the same region**, we can accept being called with **arguments with two +distinct regions**. That seems intuitively unsound. But in fact, it's fine, as +I tried to explain in [this issue][ohdeargoditsallbroken] on the Rust issue +tracker long ago. The reason is that even if we get called with arguments of +two distinct lifetimes, those two lifetimes have some intersection (the call +itself), and that intersection can be our value of `'a` that we use as the +common lifetime of our arguments. -nmatsakis) + +[ohdeargoditsallbroken]: https://github.com/rust-lang/rust/issues/32330#issuecomment-202536977 + +## Final example + +Let's look at one last example. We'll extend the previous one to have +a return type: + +```text +for<'a> fn(&'a u32, &'a u32) -> &'a u32 + <: +for<'b, 'c> fn(&'b u32, &'c u32) -> &'b u32 +``` + +Despite seeming very similar to the previous example, this case is going to get +an error. That's good: the problem is that we've gone from a fn that promises +to return one of its two arguments, to a fn that is promising to return the +first one. That is unsound. Let's see how it plays out. + +First, we replace the bound region in the supertype with a placeholder: + +```text +for<'a> fn(&'a u32, &'a u32) -> &'a u32 + <: +fn(&'!1 u32, &'!2 u32) -> &'!1 u32 +``` + +Then we instantiate the subtype with existentials (in U2): + +```text +fn(&'?3 u32, &'?3 u32) -> &'?3 u32 + <: +fn(&'!1 u32, &'!2 u32) -> &'!1 u32 +``` + +And now we create the subtyping relationships: + +```text +&'!1 u32 <: &'?3 u32 // arg 1 +&'!2 u32 <: &'?3 u32 // arg 2 +&'?3 u32 <: &'!1 u32 // return type +``` + +And finally the outlives relationships. Here, let V1, V2, and V3 be the +variables we assign to `!1`, `!2`, and `?3` respectively: + +```text +V1: V3 +V2: V3 +V3: V1 +``` + +Those variables will have these initial values: + +```text +V1 in U1 = {placeholder(1)} +V2 in U2 = {placeholder(2)} +V3 in U2 = {} +``` + +Now because of the `V3: V1` constraint, we have to add `placeholder(1)` into `V3` (and +indeed it is visible from `V3`), so we get: + +```text +V3 in U2 = {placeholder(1)} +``` + +then we have this constraint `V2: V3`, so we wind up having to enlarge +`V2` to include `placeholder(1)` (which it can also see): + +```text +V2 in U2 = {placeholder(1), placeholder(2)} +``` + +Now constraint propagation is done, but when we check the outlives +relationships, we find that `V2` includes this new element `placeholder(1)`, +so we report an error. diff --git a/src/doc/rustc-guide/src/borrow_check/two_phase_borrows.md b/src/doc/rustc-guide/src/borrow_check/two_phase_borrows.md index 753ffa5b28..09e7fbefe5 100644 --- a/src/doc/rustc-guide/src/borrow_check/two_phase_borrows.md +++ b/src/doc/rustc-guide/src/borrow_check/two_phase_borrows.md @@ -15,7 +15,7 @@ two-phase borrow are: To give some examples: -```rust +```rust2018 // In the source code // Case 1: diff --git a/src/doc/rustc-guide/src/closure.md b/src/doc/rustc-guide/src/closure.md new file mode 100644 index 0000000000..77f2b42c34 --- /dev/null +++ b/src/doc/rustc-guide/src/closure.md @@ -0,0 +1,213 @@ +# Closure Expansion in rustc + +This section describes how rustc handles closures. Closures in Rust are +effectively "desugared" into structs that contain the values they use (or +references to the values they use) from their creator's stack frame. rustc has +the job of figuring out which values a closure uses and how, so it can decide +whether to capture a given variable by shared reference, mutable reference, or +by move. rustc also has to figure out which the closure traits ([`Fn`][fn], +[`FnMut`][fn_mut], or [`FnOnce`][fn_once]) a closure is capable of +implementing. + +[fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html +[fn_mut]:https://doc.rust-lang.org/std/ops/trait.FnMut.html +[fn_once]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html + +Let's start with a few examples: + +### Example 1 + +To start, let's take a look at how the closure in the following example is desugared: + +```rust +fn closure(f: impl Fn()) { + f(); +} + +fn main() { + let x: i32 = 10; + closure(|| println!("Hi {}", x)); // The closure just reads x. + println!("Value of x after return {}", x); +} +``` + +Let's say the above is the content of a file called `immut.rs`. If we compile +`immut.rs` using the following command. The [`-Zdump-mir=all`][dump-mir] flag will cause +`rustc` to generate and dump the [MIR][mir] to a directory called `mir_dump`. +```console +> rustc +stage1 immut.rs -Zdump-mir=all +``` + +[mir]: ./mir/index.md +[dump-mir]: ./mir/passes.md + +After we run this command, we will see a newly generated directory in our +current working directory called `mir_dump`, which will contain several files. +If we look at file `rustc.main.-------.mir_map.0.mir`, we will find, among +other things, it also contains this line: + +```rust,ignore +_4 = &_1; +_3 = [closure@immut.rs:7:13: 7:36] { x: move _4 }; +``` + +Note that in the MIR examples in this chapter, `_1` is `x`. + +Here in first line `_4 = &_1;`, the `mir_dump` tells us that `x` was borrowed +as an immutable reference. This is what we would hope as our closure just +reads `x`. + +### Example 2 + +Here is another example: + +```rust +fn closure(mut f: impl FnMut()) { + f(); +} + +fn main() { + let mut x: i32 = 10; + closure(|| { + x += 10; // The closure mutates the value of x + println!("Hi {}", x) + }); + println!("Value of x after return {}", x); +} +``` + +```rust,ignore +_4 = &mut _1; +_3 = [closure@mut.rs:7:13: 10:6] { x: move _4 }; +``` +This time along, in the line `_4 = &mut _1;`, we see that the borrow is changed to mutable borrow. +Fair enough! The closure increments `x` by 10. + +### Example 3 + +One more example: + +```rust +fn closure(f: impl FnOnce()) { + f(); +} + +fn main() { + let x = vec![21]; + closure(|| { + drop(x); // Makes x unusable after the fact. + }); + // println!("Value of x after return {:?}", x); +} +``` + +```rust,ignore +_6 = [closure@move.rs:7:13: 9:6] { x: move _1 }; // bb16[3]: scope 1 at move.rs:7:13: 9:6 +``` +Here, `x` is directly moved into the closure and the access to it will not be permitted after the +closure. + +## Inferences in the compiler + +Now let's dive into rustc code and see how all these inferences are done by the compiler. + +Let's start with defining a term that we will be using quite a bit in the rest of the discussion - +*upvar*. An **upvar** is a variable that is local to the function where the closure is defined. So, +in the above examples, **x** will be an upvar to the closure. They are also sometimes referred to as +the *free variables* meaning they are not bound to the context of the closure. +[`src/librustc/ty/query/mod.rs`][upvars] defines a query called *upvars* for this purpose. + +[upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/query/queries/struct.upvars.html + +Other than lazy invocation, one other thing that the distinguishes a closure from a +normal function is that it can use the upvars. It borrows these upvars from its surrounding +context; therfore the compiler has to determine the upvar's borrow type. The compiler starts with +assigning an immutable borrow type and lowers the restriction (that is, changes it from +**immutable** to **mutable** to **move**) as needed, based on the usage. In the Example 1 above, the +closure only uses the variable for printing but does not modify it in any way and therefore, in the +`mir_dump`, we find the borrow type for the upvar `x` to be immutable. In example 2, however, the +closure modifies `x` and increments it by some value. Because of this mutation, the compiler, which +started off assigning `x` as an immutable reference type, has to adjust it as a mutable reference. +Likewise in the third example, the closure drops the vector and therefore this requires the variable +`x` to be moved into the closure. Depending on the borrow kind, the closure has to implement the +appropriate trait: `Fn` trait for immutable borrow, `FnMut` for mutable borrow, +and `FnOnce` for move semantics. + +Most of the code related to the closure is in the +[`src/librustc_typeck/check/upvar.rs`][upvar] file and the data structures are +declared in the file [`src/librustc/ty/mod.rs`][ty]. + +[upvar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/upvar/index.html +[ty]:https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/index.html + +Before we go any further, let's discuss how we can examine the flow of coontrol through the rustc +codebase. For closures specifically, set the `RUST_LOG` env variable as below and collect the +output in a file: + +```console +> RUST_LOG=rustc_typeck::check::upvar rustc +stage1 -Zdump-mir=all \ + <.rs file to compile> 2> +``` + +This uses the stage1 compiler and enables `debug!` logging for the +`rustc_typeck::check::upvar` module. + +The other option is to step through the code using lldb or gdb. + +1. `rust-lldb build/x86_64-apple-darwin/stage1/bin/rustc test.rs` +2. In lldb: + 1. `b upvar.rs:134` // Setting the breakpoint on a certain line in the upvar.rs file` + 2. `r` // Run the program until it hits the breakpoint + +Let's start with [`upvar.rs`][upvar]. This file has something called +the [`euv::ExprUseVisitor`][euv] which walks the source of the closure and +invokes a callbackfor each upvar that is borrowed, mutated, or moved. + +[euv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/middle/expr_use_visitor/struct.ExprUseVisitor.html + +```rust +fn main() { + let mut x = vec![21]; + let _cl = || { + let y = x[0]; // 1. + x[0] += 1; // 2. + }; +} +``` + +In the above example, our visitor will be called twice, for the lines marked 1 and 2, once for a +shared borrow and another one for a mutable borrow. It will also tell us what was borrowed. + +The callbacks are defined by implementing the [`Delegate`][delegate] trait. The +[`InferBorrowKind`][ibk] type implements `Delegate` and keeps a map that +records for each upvar which mode of borrow was required. The modes of borrow +can be `ByValue` (moved) or `ByRef` (borrowed). For `ByRef` borrows, it can be +`shared`, `shallow`, `unique` or `mut` as defined in the +[`src/librustc/mir/mod.rs`][mir_mod]. + +[mir_mod]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/index.html + +`Delegate` defines a few different methods (the different callbacks): +**consume**: for *move* of a variable, **borrow** for a *borrow* of some kind +(shared or mutable), and **mutate** when we see an *assignment* of something. + +All of these callbacks have a common argument *cmt* which stands for Category, +Mutability and Type and is defined in +[`src/librustc/middle/mem_categorization.rs`][cmt]. Borrowing from the code +comments, "`cmt` is a complete categorization of a value indicating where it +originated and how it is located, as well as the mutability of the memory in +which the value is stored". Based on the callback (consume, borrow etc.), we +will call the relevant *adjust_upvar_borrow_kind_for_* and pass the +`cmt` along. Once the borrow type is adjusted, we store it in the table, which +basically says what borrows were made for each closure. + +```rust,ignore +self.tables + .borrow_mut() + .upvar_capture_map + .extend(delegate.adjust_upvar_captures); +``` + +[delegate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/middle/expr_use_visitor/trait.Delegate.html +[ibk]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/upvar/struct.InferBorrowKind.html +[cmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/middle/mem_categorization/index.html diff --git a/src/doc/rustc-guide/src/compiler-debugging.md b/src/doc/rustc-guide/src/compiler-debugging.md index db7f08e465..8f3a331aa6 100644 --- a/src/doc/rustc-guide/src/compiler-debugging.md +++ b/src/doc/rustc-guide/src/compiler-debugging.md @@ -46,9 +46,10 @@ stack backtrace: 37: rustc_driver::run_compiler ``` -If you want line numbers for the stack trace, you can enable -`debuginfo-lines=true` or `debuginfo=true` in your config.toml and rebuild the -compiler. Then the backtrace will look like this: +If you want line numbers for the stack trace, you can enable `debug = true` in +your config.toml and rebuild the compiler (`debuginfo-level = 1` will also add +line numbers, but `debug = true` gives full debuginfo). Then the backtrace will +look like this: ```text stack backtrace: @@ -128,11 +129,11 @@ note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. stack backtrace: (~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~) - 7: rustc::traits::error_reporting::>::report_selection_error + 7: rustc::traits::error_reporting::> + ::report_selection_error at /home/user/rust/src/librustc/traits/error_reporting.rs:823 - 8: rustc::traits::error_reporting::>::report_fulfillment_errors + 8: rustc::traits::error_reporting::> + ::report_fulfillment_errors at /home/user/rust/src/librustc/traits/error_reporting.rs:160 at /home/user/rust/src/librustc/traits/error_reporting.rs:112 9: rustc_typeck::check::FnCtxt::select_obligations_where_possible diff --git a/src/doc/rustc-guide/src/compiler-team.md b/src/doc/rustc-guide/src/compiler-team.md index 0f0808b79a..968e2f1429 100644 --- a/src/doc/rustc-guide/src/compiler-team.md +++ b/src/doc/rustc-guide/src/compiler-team.md @@ -95,7 +95,7 @@ The guidelines for reviewers are as follows: ### high-five -Once you have r+ rights, you can also be added to the high-five +Once you have r+ rights, you can also be added to the [high-five][hi5] rotation. high-five is the bot that assigns incoming PRs to reviewers. If you are added, you will be randomly selected to review PRs. If you find you are assigned a PR that you don't feel comfortable diff --git a/src/doc/rustc-guide/src/conventions.md b/src/doc/rustc-guide/src/conventions.md index d9f462a053..3660f33790 100644 --- a/src/doc/rustc-guide/src/conventions.md +++ b/src/doc/rustc-guide/src/conventions.md @@ -141,8 +141,7 @@ to the compiler. - `cx` tends to be short for "context" and is often used as a suffix. For example, `tcx` is a common name for the [Typing Context][tcx]. -- [`'tcx` and `'gcx`][tcx] are used as the lifetime names for the Typing - Context. +- [`'tcx`][tcx] is used as the lifetime name for the Typing Context. - Because `crate` is a keyword, if you need a variable to represent something crate-related, often the spelling is changed to `krate`. diff --git a/src/doc/rustc-guide/src/debugging-support-in-rustc.md b/src/doc/rustc-guide/src/debugging-support-in-rustc.md new file mode 100644 index 0000000000..1775b07af5 --- /dev/null +++ b/src/doc/rustc-guide/src/debugging-support-in-rustc.md @@ -0,0 +1,321 @@ +# Debugging support in the Rust compiler + +This document explains the state of debugging tools support in the Rust compiler (rustc). +The document gives an overview of debugging tools like GDB, LLDB etc. and infrastrcture +around Rust compiler to debug Rust code. If you want to learn how to debug the Rust compiler +itself, then you must see [Debugging the Compiler] page. + +The material is gathered from YouTube video [Tom Tromey discusses debugging support in rustc]. + +## Preliminaries + +### Debuggers + +According to Wikipedia + +> A [debugger or debugging tool] is a computer program that is used to test and debug +> other programs (the "target" program). + +Writing a debugger from scratch for a language requires a lot of work, especially if +debuggers have to be supported on various platforms. GDB and LLDB, however, can be +extended to support debugging a language. This is the path that Rust has chosen. +This document's main goal is to document the said debuggers support in Rust compiler. + +### DWARF + +According to the [DWARF] standard website + +> DWARF is a debugging file format used by many compilers and debuggers to support source level +> debugging. It addresses the requirements of a number of procedural languages, +> such as C, C++, and Fortran, and is designed to be extensible to other languages. +> DWARF is architecture independent and applicable to any processor or operating system. +> It is widely used on Unix, Linux and other operating systems, +> as well as in stand-alone environments. + +DWARF reader is a program that consumes the DWARF format and creates debugger compatible output. +This program may live in the compiler itself. DWARF uses a data structure called +Debugging Information Entry (DIE) which stores the information as "tags" to denote functions, +variables etc., e.g., `DW_TAG_variable`, `DW_TAG_pointer_type`, `DW_TAG_subprogram` etc. +You can also invent your own tags and attributes. + +## Supported debuggers + +### GDB + +We have our own fork of GDB - [https://github.com/rust-dev-tools/gdb] + +#### Rust expression parser + +To be able to show debug output we need an expression parser. +This (GDB) expression parser is written in [Bison] and is only a subset of Rust expressions. +This means that this parser can parse only a subset of Rust expressions. +GDB parser was written from scratch and has no relation to any other parser. +For example, this parser is not related to Rustc's parser. + +GDB has Rust like value and type output. It can print values and types in a way +that look like Rust syntax in the output. Or when you print a type as [ptype] in GDB, +it also looks like Rust source code. Checkout the documentation in the [manual for GDB/Rust]. + +#### Parser extensions + +Expression parser has a couple of extensions in it to facilitate features that you cannot do +with Rust. Some limitations are listed in the [manual for GDB/Rust]. There is some special +code in the DWARF reader in GDB to support the extensions. + +A couple of examples of DWARF reader support needed are as follows - + +1. Enum: Needed for support for enum types. The Rustc writes the information about enum into +DWARF and GDB reads the DWARF to understand where is the tag field or is there a tag +field or is the tag slot shared with non-zero optimization etc. + +2. Dissect trait objects: DWARF extension where the trait object's description in the DWARF +also points to a stub description of the corresponding vtable which in turn points to the +concrete type for which this trait object exists. This means that you can do a `print *object` +for that trait object, and GDB will understand how to find the correct type of the payload in +the trait object. + +**TODO**: Figure out if the following should be mentioned in the GDB-Rust document rather than +this guide page so there is no duplication. This is regarding the following comments: + +[This comment by Tom](https://github.com/rust-lang/rustc-guide/pull/316#discussion_r284027340) +> gdb's Rust extensions and limitations are documented in the gdb manual: +https://sourceware.org/gdb/onlinedocs/gdb/Rust.html -- however, this neglects to mention that +gdb convenience variables and registers follow the gdb $ convention, and that the Rust parser +implements the gdb @ extension. + +[This question by Aman](https://github.com/rust-lang/rustc-guide/pull/316#discussion_r285401353) +> @tromey do you think we should mention this part in the GDB-Rust document rather than this +document so there is no duplication etc.? + +#### Developer notes + +* This work is now upstream. Bugs can be reported in [GDB Bugzilla]. + +### LLDB + +We have our own fork of LLDB - [https://github.com/rust-lang/lldb] + +Fork of LLVM project - [https://github.com/rust-lang/llvm-project] + +LLDB currently only works on macOS because of a dependency issue. This issue was easier to +solve for macOS as compared to Linux. However, Tom has a possible solution which can enable +us to ship LLDB everywhere. + +#### Rust expression parser + +This expression parser is written in C++. It is a type of [Recursive Descent parser]. +Implements slightly less of the Rust language than GDB. LLDB has Rust like value and type output. + +#### Parser extensions + +There is some special code in the DWARF reader in LLDB to support the extensions. +A couple of examples of DWARF reader support needed are as follows - + +1. Enum: Needed for support for enum types. The Rustc writes the information about +enum into DWARF and LLDB reads the DWARF to understand where is the tag field or +is there a tag field or is the tag slot shared with non-zero optimization etc. +In other words, it has enum support as well. + +#### Developer notes + +* None of the LLDB work is upstream. This [rust-lang/lldb wiki page] explains a few details. +* The reason for forking LLDB is that LLDB recently removed all the other language plugins +due to lack of maintenance. +* LLDB has a plugin architecture but that does not work for language support. +* LLDB is available via Rust build (`rustup`). +* GDB generally works better on Linux. + +## DWARF and Rustc + +[DWARF] is the standard way compilers generate debugging information that debuggers read. +It is _the_ debugging format on macOS and Linux. It is a multi-language, extensible format +and is mostly good enough for Rust's purposes. Hence, the current implementation reuses DWARF's +concepts. This is true even if some of the concepts in DWARF do not align with Rust +semantically because generally there can be some kind of mapping between the two. + +We have some DWARF extensions that the Rust compiler emits and the debuggers understand that +are _not_ in the DWARF standard. + +* Rust compiler will emit DWARF for a virtual table, and this `vtable` object will have a + `DW_AT_containing_type` that points to the real type. This lets debuggers dissect a trait object + pointer to correctly find the payload. E.g., here's such a DIE, from a test case in the gdb + repository: + + ```asm + <1><1a9>: Abbrev Number: 3 (DW_TAG_structure_type) + <1aa> DW_AT_containing_type: <0x1b4> + <1ae> DW_AT_name : (indirect string, offset: 0x23d): vtable + <1b2> DW_AT_byte_size : 0 + <1b3> DW_AT_alignment : 8 + ``` + +* The other extension is that the Rust compiler can emit a tagless discriminated union. + See [DWARF feature request] for this item. + +### Current limitations of DWARF + +* Traits - require a bigger change than normal to DWARF, on how to represent Traits in DWARF. +* DWARF provides no way to differentiate between Structs and Tuples. Rust compiler emits +fields with `__0` and debuggers look for a sequence of such names to overcome this limitation. +For example, in this case the debugger would look at a field via `x.__0` instead of `x.0`. +This is resolved via the Rust parser in the debugger so now you can do `x.0`. + +DWARF relies on debuggers to know some information about platform ABI. +Rust does not do that all the time. + +## Developer notes + +This section is from the talk about certain aspects of development. + +## What is missing + +### Shipping GDB in Rustup + +Tracking issue: [https://github.com/rust-lang/rust/issues/34457] + +Shipping GDB requires change to Rustup delivery system. To manage Rustup build size and +times we need to build GDB separately, on its own and somehow provide the artifacts produced +to be included in the final build. However, if we can ship GDB with rustup, it will simplify +the development process by having compiler emit new debug info which can be readily consumed. + +Main issue in achieving this is setting up dependencies. One such dependency is Python. That +is why we have our own fork of GDB because one of the drivers is patched on Rust's side to +check the correct version of Python (Python 2.7 in this case. *Note: Python3 is not chosen +for this purpose because Python's stable ABI is limited and is not sufficient for GDB's needs. +See [https://docs.python.org/3/c-api/stable.html]*). + +This is to keep updates to debugger as fast as possible as we make changes to the debugging symbols. +In essence, to ship the debugger as soon as new debugging info is added. GDB only releases +every six months or so. However, the changes that are +not related to Rust itself should ideally be first merged to upstream eventually. + +### Code signing for LLDB debug server on macOS + +According to Wikipedia, [System Integrity Protection] is + +> System Integrity Protection (SIP, sometimes referred to as rootless) is a security feature +> of Apple's macOS operating system introduced in OS X El Capitan. It comprises a number of +> mechanisms that are enforced by the kernel. A centerpiece is the protection of system-owned +> files and directories against modifications by processes without a specific "entitlement", +> even when executed by the root user or a user with root privileges (sudo). + +It prevents processes using `ptrace` syscall. If a process wants to use `ptrace` it has to be +code signed. The certificate that signs it has to be trusted on your machine. + +See [Apple developer documentation for System Integrity Protection]. + +We may need to sign up with Apple and get the keys to do this signing. Tom has looked into if +Mozilla cannot do this because it is at the maximum number of +keys it is allowed to sign. Tom does not know if Mozilla could get more keys. + +Alternatively, Tom suggests that maybe a Rust legal entity is needed to get the keys via Apple. +This problem is not technical in nature. If we had such a key we could sign GDB as well and +ship that. + +### DWARF and Traits + +Rust traits are not emitted into DWARF at all. The impact of this is calling a method `x.method()` +does not work as is. The reason being that method is implemented by a trait, as opposed +to a type. That information is not present so finding trait methods is missing. + +DWARF has a notion of interface types (possibly added for Java). Tom's idea was to use this +interface type as traits. + +DWARF only deals with concrete names, not the reference types. So, a given implementation of a +trait for a type would be one of these interfaces (`DW_tag_interface` type). Also, the type for +which it is implemented would describe all the interfaces this type implements. This requires a +DWARF extension. + +Issue on Github: [https://github.com/rust-lang/rust/issues/33014] + +## Typical process for a Debug Info change (LLVM) + +LLVM has Debug Info (DI) builders. This is the primary thing that Rust calls into. +This is why we need to change LLVM first because that is emitted first and not DWARF directly. +This is a kind of metadata that you construct and hand-off to LLVM. For the Rustc/LLVM hand-off +some LLVM DI builder methods are called to construct representation of a type. + +The steps of this process are as follows - + +1. LLVM needs changing. + + LLVM does not emit Interface types at all, so this needs to be implemented in the LLVM first. + + Get sign off on LLVM maintainers that this is a good idea. + +2. Change the DWARF extension. + +3. Update the debuggers. + + Update DWARF readers, expression evaluators. + +4. Update Rust compiler. + + Change it to emit this new information. + +### Procedural macro stepping + +A deeply profound question is that how do you actually debug a procedural macro? +What is the location you emit for a macro expansion? Consider some of the following cases - + +* You can emit location of the invocation of the macro. +* You can emit the location of the definition of the macro. +* You can emit locations of the content of the macro. + +RFC: [https://github.com/rust-lang/rfcs/pull/2117] + +Focus is to let macros decide what to do. This can be achieved by having some kind of attribute +that lets the macro tell the compiler where the line marker should be. This affects where you +set the breakpoints and what happens when you step it. + +## Future work + +#### Name mangling changes + +* New demangler in `libiberty` (gcc source tree). +* New demangler in LLVM or LLDB. + +**TODO**: Check the location of the demangler source. +[Question on Github](https://github.com/rust-lang/rustc-guide/pull/316#discussion_r283062536). + +#### Reuse Rust compiler for expressions + +This is an important idea because debuggers by and large do not try to implement type +inference. You need to be much more explicit when you type into the debugger than your +actual source code. So, you cannot just copy and paste an expression from your source +code to debugger and expect the same answer but this would be nice. This can be helped +by using compiler. + +It is certainly doable but it is a large project. You certainly need a bridge to the +debugger because the debugger alone has access to the memory. Both GDB (gcc) and LLDB (clang) +have this feature. LLDB uses Clang to compile code to JIT and GDB can do the same with GCC. + +Both debuggers expression evaluation implement both a superset and a subset of Rust. +They implement just the expression language but they also add some extensions like GDB has +convenience variables. Therefore, if you are taking this route then you not only need +to do this bridge but may have to add some mode to let the compiler understand some extensions. + +#### Windows debugging (PDB) is missing + +This is a complete unknown. + +[Tom Tromey discusses debugging support in rustc]: https://www.youtube.com/watch?v=elBxMRSNYr4 +[Debugging the Compiler]: compiler-debugging.md +[debugger or debugging tool]: https://en.wikipedia.org/wiki/Debugger +[Bison]: https://www.gnu.org/software/bison/ +[ptype]: https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_109.html +[rust-lang/lldb wiki page]: https://github.com/rust-lang/lldb/wiki +[DWARF]: http://dwarfstd.org +[manual for GDB/Rust]: https://sourceware.org/gdb/onlinedocs/gdb/Rust.html +[GDB Bugzilla]: https://sourceware.org/bugzilla/ +[Recursive Descent parser]: https://en.wikipedia.org/wiki/Recursive_descent_parser +[System Integrity Protection]: https://en.wikipedia.org/wiki/System_Integrity_Protection +[https://github.com/rust-dev-tools/gdb]: https://github.com/rust-dev-tools/gdb +[DWARF feature request]: http://dwarfstd.org/ShowIssue.php?issue=180517.2 +[https://docs.python.org/3/c-api/stable.html]: https://docs.python.org/3/c-api/stable.html +[https://github.com/rust-lang/rfcs/pull/2117]: https://github.com/rust-lang/rfcs/pull/2117 +[https://github.com/rust-lang/rust/issues/33014]: https://github.com/rust-lang/rust/issues/33014 +[https://github.com/rust-lang/rust/issues/34457]: https://github.com/rust-lang/rust/issues/34457 +[Apple developer documentation for System Integrity Protection]: https://developer.apple.com/library/archive/releasenotes/MacOSX/WhatsNewInOSX/Articles/MacOSX10_11.html#//apple_ref/doc/uid/TP40016227-SW11 +[https://github.com/rust-lang/lldb]: https://github.com/rust-lang/lldb +[https://github.com/rust-lang/llvm-project]: https://github.com/rust-lang/llvm-project diff --git a/src/doc/rustc-guide/src/diag.md b/src/doc/rustc-guide/src/diagnostics.md similarity index 99% rename from src/doc/rustc-guide/src/diag.md rename to src/doc/rustc-guide/src/diagnostics.md index 31268e9f6f..f3d5187647 100644 --- a/src/doc/rustc-guide/src/diag.md +++ b/src/doc/rustc-guide/src/diagnostics.md @@ -1,4 +1,4 @@ -# Emitting Diagnostics +# Emitting Errors and other Diagnostics A lot of effort has been put into making `rustc` have great error messages. This chapter is about how to emit compile errors and lints from the compiler. diff --git a/src/doc/rustc-guide/src/diag/json-format.md b/src/doc/rustc-guide/src/diagnostics/json-format.md similarity index 100% rename from src/doc/rustc-guide/src/diag/json-format.md rename to src/doc/rustc-guide/src/diagnostics/json-format.md diff --git a/src/doc/rustc-guide/src/how-to-build-and-run.md b/src/doc/rustc-guide/src/how-to-build-and-run.md index 6d5bcb916b..84efffc84b 100644 --- a/src/doc/rustc-guide/src/how-to-build-and-run.md +++ b/src/doc/rustc-guide/src/how-to-build-and-run.md @@ -1,4 +1,4 @@ -# How to build the compiler and run what you built +# How to Build and Run the Compiler The compiler is built using a tool called `x.py`. You will need to have Python installed to run it. But before we get to that, if you're going to @@ -28,46 +28,57 @@ settings (and possibly others, such as `llvm.ccache`): assertions = true [rust] -# This enables some assertions, but more importantly it enables the `debug!` -# logging macros that are essential for debugging rustc. -debug-assertions = true - # This will make your build more parallel; it costs a bit of runtime # performance perhaps (less inlining) but it's worth it. codegen-units = 0 -# I always enable full debuginfo, though debuginfo-lines is more important. -debuginfo = true - -# Gives you line numbers for backtraces. -debuginfo-lines = true +# This enables full debuginfo and debug assertions. The line debuginfo is also +# enabled by `debuginfo-level = 1`. Full debuginfo is also enabled by +# `debuginfo-level = 2`. Debug assertions can also be enabled with +# `debug-assertions = true`. Note that `debug = true` will make your build +# slower, so you may want to try individually enabling debuginfo and assertions +# or enable only line debuginfo which is basically free. +debug = true ``` -### What is x.py? +If you have already built `rustc`, then you may have to execute `rm -rf build` for subsequent +configuration changes to take effect. Note that `./x.py clean` will not cause a +rebuild of LLVM, so if your configuration change affects LLVM, you will need to +manually `rm -rf build/` before rebuilding. + +### What is `x.py`? -x.py is the script used to orchestrate the tooling in the rustc repository. -It is the script that can build docs, run tests, and compile rustc. -It is the now preferred way to build rustc and it replaces the old makefiles -from before. Below are the different ways to utilize x.py in order to +`x.py` is the script used to orchestrate the tooling in the `rustc` repository. +It is the script that can build docs, run tests, and compile `rustc`. +It is the now preferred way to build `rustc` and it replaces the old makefiles +from before. Below are the different ways to utilize `x.py` in order to effectively deal with the repo for various common tasks. -### Running x.py and building a stage1 compiler +### Running `x.py` and building a stage1 compiler One thing to keep in mind is that `rustc` is a _bootstrapping_ compiler. That is, since `rustc` is written in Rust, we need to use an older version of the compiler to compile the newer version. In -particular, the newer version of the compiler, `libstd`, and other -tooling may use some unstable features internally. The result is that -compiling `rustc` is done in stages: - -- **Stage 0:** the stage0 compiler is usually the current _beta_ compiler - (`x.py` will download it for you); you can configure `x.py` to use something - else, though. +particular, the newer version of the compiler and some of the artifacts needed +to build it, such as `libstd` and other tooling, may use some unstable features +internally, requiring a specific version which understands these unstable +features. + +The result is that compiling `rustc` is done in stages: + +- **Stage 0:** the stage0 compiler is usually (you can configure `x.py` to use + something else) the current _beta_ `rustc` compiler and its associated dynamic + libraries (which `x.py` will download for you). This stage0 compiler is then + used only to compile `rustbuild`, `std`, `test`, and `rustc`. When compiling + `test` and `rustc`, this stage0 compiler uses the freshly compiled `std`. + There are two concepts at play here: a compiler (with its set of dependencies) + and its 'target' or 'object' libraries (`std`, `test`, and `rustc`). + Both are staged, but in a staggered manner. - **Stage 1:** the code in your clone (for new version) is then compiled with the stage0 compiler to produce the stage1 compiler. However, it was built with an older compiler (stage0), so to - optimize the stage1 compiler we go to next stage. - - (In theory, the stage1 compiler is functionally identical to the + optimize the stage1 compiler we go to next the stage. + - In theory, the stage1 compiler is functionally identical to the stage2 compiler, but in practice there are subtle differences. In particular, the stage1 compiler itself was built by stage0 and hence not by the source in your working directory: this means that @@ -75,22 +86,197 @@ compiling `rustc` is done in stages: symbol names that would have been made by the stage1 compiler. This can be important when using dynamic linking (e.g., with derives. Sometimes this means that some tests don't work when run - with stage1.) + with stage1. - **Stage 2:** we rebuild our stage1 compiler with itself to produce the stage2 compiler (i.e. it builds itself) to have all the _latest optimizations_. (By default, we copy the stage1 libraries for use by the stage2 compiler, since they ought to be identical.) -- _(Optional)_ **Stage 3**: to sanity check of our new compiler, we +- _(Optional)_ **Stage 3**: to sanity check our new compiler, we can build the libraries with the stage2 compiler. The result ought to be identical to before, unless something has broken. +#### A note on stage meanings + +When running `x.py` you will see output such as: + +```txt +Building stage0 std artifacts +Copying stage0 std from stage0 +Building stage0 test artifacts +Copying stage0 test from stage0 +Building stage0 compiler artifacts +Copying stage0 rustc from stage0 +Building LLVM for x86_64-apple-darwin +Building stage0 codegen artifacts +Assembling stage1 compiler +Building stage1 std artifacts +Copying stage1 std from stage1 +Building stage1 test artifacts +Copying stage1 test from stage1 +Building stage1 compiler artifacts +Copying stage1 rustc from stage1 +Building stage1 codegen artifacts +Assembling stage2 compiler +Uplifting stage1 std +Copying stage2 std from stage1 +Generating unstable book md files +Building stage0 tool unstable-book-gen +Building stage0 tool rustbook +Documenting standalone +Building rustdoc for stage2 +Documenting book redirect pages +Documenting stage2 std +Building rustdoc for stage1 +Documenting stage2 test +Documenting stage2 whitelisted compiler +Documenting stage2 compiler +Documenting stage2 rustdoc +Documenting error index +Uplifting stage1 test +Copying stage2 test from stage1 +Uplifting stage1 rustc +Copying stage2 rustc from stage1 +Building stage2 tool error_index_generator +``` + +A deeper look into `x.py`'s phases can be seen here: + +A diagram of the rustc compilation phases + +Keep in mind this diagram is a simplification, i.e. `rustdoc` can be built at +different stages, the process is a bit different when passing flags such as +`--keep-stage`, or if there are non-host targets. + +The following tables indicate the outputs of various stage actions: + +| Stage 0 Action | Output | +|-----------------------------------------------------------|----------------------------------------------| +| `beta` extracted | `build/HOST/stage0` | +| `stage0` builds `bootstrap` | `build/bootstrap` | +| `stage0` builds `libstd` | `build/HOST/stage0-std/TARGET` | +| copy `stage0-std` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | +| `stage0` builds `libtest` with `stage0-sysroot` | `build/HOST/stage0-test/TARGET` | +| copy `stage0-test` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | +| `stage0` builds `rustc` with `stage0-sysroot` | `build/HOST/stage0-rustc/HOST` | +| copy `stage0-rustc (except executable)` | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | +| build `llvm` | `build/HOST/llvm` | +| `stage0` builds `codegen` with `stage0-sysroot` | `build/HOST/stage0-codgen/HOST` | +| `stage0` builds `rustdoc` with `stage0-sysroot` | `build/HOST/stage0-tools/HOST` | + +`--stage=0` stops here. + +| Stage 1 Action | Output | +|-----------------------------------------------------|---------------------------------------| +| copy (uplift) `stage0-rustc` executable to `stage1` | `build/HOST/stage1/bin` | +| copy (uplift) `stage0-codegen` to `stage1` | `build/HOST/stage1/lib` | +| copy (uplift) `stage0-sysroot` to `stage1` | `build/HOST/stage1/lib` | +| `stage1` builds `libstd` | `build/HOST/stage1-std/TARGET` | +| copy `stage1-std` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` | +| `stage1` builds `libtest` | `build/HOST/stage1-test/TARGET` | +| copy `stage1-test` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` | +| `stage1` builds `rustc` | `build/HOST/stage1-rustc/HOST` | +| copy `stage1-rustc` (except executable) | `build/HOST/stage1/lib/rustlib/HOST` | +| `stage1` builds `codegen` | `build/HOST/stage1-codegen/HOST` | + +`--stage=1` stops here. + +| Stage 2 Action | Output | +|-------------------------------------------|-----------------------------------------------------------------| +| copy (uplift) `stage1-rustc` executable | `build/HOST/stage2/bin` | +| copy (uplift) `stage1-sysroot` | `build/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST` | +| `stage2` builds `libstd` (except HOST?) | `build/HOST/stage2-std/TARGET` | +| copy `stage2-std` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` | +| `stage2` builds `libtest` (except HOST?) | `build/HOST/stage2-test/TARGET` | +| copy `stage2-test` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` | +| `stage2` builds `rustdoc` | `build/HOST/stage2-tools/HOST` | +| copy `rustdoc` | `build/HOST/stage2/bin` | + +`--stage=2` stops here. + +Note that the convention `x.py` uses is that: +- A "stage N artifact" is an artifact that is _produced_ by the stage N compiler. +- The "stage (N+1) compiler" is assembled from "stage N artifacts". +- A `--stage N` flag means build _with_ stage N. + +In short, _stage 0 uses the stage0 compiler to create stage0 artifacts which +will later be uplifted to stage1_. + +Every time any of the main artifacts (`std`, `test`, `rustc`) are compiled, two +steps are performed. +When `std` is compiled by a stage N compiler, that `std` will be linked to +programs built by the stage N compiler (including test and `rustc` built later +on). It will also be used by the stage (N+1) compiler to link against itself. +This is somewhat intuitive if one thinks of the stage (N+1) compiler as "just" +another program we are building with the stage N compiler. In some ways, `rustc` +(the binary, not the `rustbuild` step) could be thought of as one of the few +`no_core` binaries out there. + +So "stage0 std artifacts" are in fact the output of the downloaded stage0 +compiler, and are going to be used for anything built by the stage0 compiler: +e.g. `rustc`, `test` artifacts. When it announces that it is "building stage1 +std artifacts" it has moved on to the next bootstrapping phase. This pattern +continues in latter stages. + +Also note that building host `std` and target `std` are different based on the +stage (e.g. see in the table how stage2 only builds non-host `std` targets. +This is because during stage2, the host `std` is uplifted from the "stage 1" +`std` -- specifically, when "Building stage 1 artifacts" is announced, it is +later copied into stage2 as well (both the compiler's `libdir` and the +`sysroot`). + +This `std` is pretty much necessary for any useful work with the compiler. +Specifically, it's used as the `std` for programs compiled by the newly compiled +compiler (so when you compile `fn main() { }` it is linked to the last `std` +compiled with `x.py build --stage 1 src/libstd`). + +The `rustc` generated by the stage0 compiler is linked to the freshly-built +`libstd`, which means that for the most part only `std` needs to be cfg-gated, +so that `rustc` can use featured added to std immediately after their addition, +without need for them to get into the downloaded beta. The `libstd` built by the +`stage1/bin/rustc` compiler, also known as "stage1 std artifacts", is not +necessarily ABI-compatible with that compiler. +That is, the `rustc` binary most likely could not use this `std` itself. +It is however ABI-compatible with any programs that the `stage1/bin/rustc` +binary builds (including itself), so in that sense they're paired. + +This is also where `--keep-stage 1 src/libstd` comes into play. Since most +changes to the compiler don't actually change the ABI, once you've produced a +`libstd` in stage 1, you can probably just reuse it with a different compiler. +If the ABI hasn't changed, you're good to go, no need to spend the time +recompiling that `std`. +`--keep-stage` simply assumes the previous compile is fine and copies those +artifacts into the appropriate place, skipping the cargo invocation. + +The reason we first build `std`, then `test`, then `rustc`, is largely just +because we want to minimize `cfg(stage0)` in the code for `rustc`. +Currently `rustc` is always linked against a "new" `std`/`test` so it doesn't +ever need to be concerned with differences in std; it can assume that the std is +as fresh as possible. + +The reason we need to build it twice is because of ABI compatibility. +The beta compiler has it's own ABI, and then the `stage1/bin/rustc` compiler +will produce programs/libraries with the new ABI. +We used to build three times, but because we assume that the ABI is constant +within a codebase, we presume that the libraries produced by the "stage2" +compiler (produced by the `stage1/bin/rustc` compiler) is ABI-compatible with +the `stage1/bin/rustc` compiler's produced libraries. +What this means is that we can skip that final compilation -- and simply use the +same libraries as the `stage2/bin/rustc` compiler uses itself for programs it +links against. + +This `stage2/bin/rustc` compiler is shipped to end-users, along with the +`stage 1 {std,test,rustc}` artifacts. + +If you want to learn more about `x.py`, read its README.md +[here](https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md). + #### Build Flags -There are other flags you can pass to the build portion of x.py that can be +There are other flags you can pass to the build command of `x.py` that can be beneficial to cutting down compile times or fitting other things you might need to change. They are: -```bash +```txt Options: -v, --verbose use verbose output (-vv for very verbose) -i, --incremental use incremental compilation @@ -127,16 +313,17 @@ probably the best "go to" command for building a local rust: This may *look* like it only builds libstd, but that is not the case. What this command does is the following: -- Build libstd using the stage0 compiler (using incremental) -- Build librustc using the stage0 compiler (using incremental) +- Build `libstd` using the stage0 compiler (using incremental) +- Build `librustc` using the stage0 compiler (using incremental) - This produces the stage1 compiler - Build libstd using the stage1 compiler (cannot use incremental) This final product (stage1 compiler + libs built using that compiler) -is what you need to build other rust programs. +is what you need to build other rust programs (unless you use `#![no_std]` or +`#![no_core]`). -Note that the command includes the `-i` switch. This enables incremental -compilation. This will be used to speed up the first two steps of the process: +The command includes the `-i` switch which enables incremental compilation. +This will be used to speed up the first two steps of the process: in particular, if you make a small change, we ought to be able to use your old results to make producing the stage1 **compiler** faster. @@ -145,15 +332,15 @@ stage1 libraries. This is because incremental only works when you run the *same compiler* twice in a row. In this case, we are building a *new stage1 compiler* every time. Therefore, the old incremental results may not apply. **As a result, you will probably find that -building the stage1 libstd is a bottleneck for you** -- but fear not, +building the stage1 `libstd` is a bottleneck for you** -- but fear not, there is a (hacky) workaround. See [the section on "recommended workflows"](#workflow) below. -Note that this whole command just gives you a subset of the full rustc -build. The **full** rustc build (what you get if you just say `./x.py +Note that this whole command just gives you a subset of the full `rustc` +build. The **full** `rustc` build (what you get if you just say `./x.py build`) has quite a few more steps: -- Build librustc and rustc with the stage1 compiler. +- Build `librustc` and `rustc` with the stage1 compiler. - The resulting compiler here is called the "stage2" compiler. - Build libstd with stage2 compiler. - Build librustdoc and a bunch of other things with the stage2 compiler. @@ -185,12 +372,11 @@ compile. Using these commands you can test that it compiles before doing a bigger build to make sure it works with the compiler. As shown before you can also pass flags at the end such as --stage. - ### Creating a rustup toolchain -Once you have successfully built rustc, you will have created a bunch +Once you have successfully built `rustc`, you will have created a bunch of files in your `build` directory. In order to actually run the -resulting rustc, we recommend creating rustup toolchains. The first +resulting `rustc`, we recommend creating rustup toolchains. The first one will run the stage1 compiler (which we built above). The second will execute the stage2 compiler (which we did not build, but which you will likely need to build at some point; for example, if you want @@ -207,7 +393,7 @@ The `` would typically be one of the following: - Mac: `x86_64-apple-darwin` - Windows: `x86_64-pc-windows-msvc` -Now you can run the rustc you built with. If you run with `-vV`, you +Now you can run the `rustc` you built with. If you run with `-vV`, you should see a version number ending in `-dev`, indicating a build from your local environment: @@ -226,8 +412,7 @@ LLVM version: 4.0 ### Suggested workflows for faster builds of the compiler -There are two workflows that are useful for faster builds of the -compiler. +There are two workflows that are useful for faster builds of the compiler. **Check, check, and check again.** The first workflow, which is useful when doing simple refactorings, is to run `./x.py check` @@ -257,12 +442,15 @@ The sequence of commands you want is as follows: - Initial build: `./x.py build -i --stage 1 src/libstd` - As [documented above](#command), this will build a functional - stage1 compiler + stage1 compiler as part of running all stage0 commands (which include + building a `libstd` compatible with the stage1 compiler) as well as the + first few steps of the "stage 1 actions" up to "stage1 (sysroot stage1) + builds libstd". - Subsequent builds: `./x.py build -i --stage 1 src/libstd --keep-stage 1` - Note that we added the `--keep-stage 1` flag here -The effect of `--keep-stage 1` is that we just *assume* that the old -standard library can be re-used. If you are editing the compiler, this +As mentioned, the effect of `--keep-stage 1` is that we just *assume* that the +old standard library can be re-used. If you are editing the compiler, this is almost always true: you haven't changed the standard library, after all. But sometimes, it's not true: for example, if you are editing the "metadata" part of the compiler, which controls how the compiler @@ -276,15 +464,14 @@ using `--keep-stage 1`** -- for example, strange should simply remove the `--keep-stage 1` from the command and rebuild. That ought to fix the problem. -You can also use `--keep-stage 1` when running tests. Something like -this: +You can also use `--keep-stage 1` when running tests. Something like this: - Initial test run: `./x.py test -i --stage 1 src/test/ui` - Subsequent test run: `./x.py test -i --stage 1 src/test/ui --keep-stage 1` -### Other x.py commands +### Other `x.py` commands -Here are a few other useful x.py commands. We'll cover some of them in detail +Here are a few other useful `x.py` commands. We'll cover some of them in detail in other sections: - Building things: @@ -297,6 +484,10 @@ in other sections: more details): - `./x.py test --stage 1 src/libstd` – runs the `#[test]` tests from libstd - `./x.py test --stage 1 src/test/run-pass` – runs the `run-pass` test suite + - `./x.py test --stage 1 src/test/ui/const-generics` - runs all the tests in + the `const-generics/` subdirectory of the `ui` test suite + - `./x.py test --stage 1 src/test/ui/const-generics/const-types.rs` - runs + the single test `const-types.rs` from the `ui` test suite ### ctags diff --git a/src/doc/rustc-guide/src/img/rustc_stages.svg b/src/doc/rustc-guide/src/img/rustc_stages.svg new file mode 100644 index 0000000000..b6671aa7cc --- /dev/null +++ b/src/doc/rustc-guide/src/img/rustc_stages.svg @@ -0,0 +1,2 @@ + +
Download
Download
beta
beta
stage0
stage0
Builds
Builds
stage0
stage0
Outputs
Outputs
libstd
libstd
Copy
Copy
stage0-std
stage0-std
stage0-sysroot
stage0-sysroot
Builds
Builds
stage0
stage0
Outputs
Outputs
libtest
libtest
Copy
Copy
stage0-test
stage0-test
stage0-sysroot
stage0-sysroot
Builds
Builds
stage0
stage0
Outputs
Outputs
rustc
rustc
Copy
Copy
stage0-rustc
stage0-rustc
stage0-sysroot
stage0-sysroot
llvm
llvm
Builds
Builds
stage0
stage0
Outputs
Outputs
codegen
codegen
stage0-codegen
stage0-codegen
Stage 0
Stage 0
Copy
Copy
stage0-rustc
stage0-codegen
stage0-sysroot
[Not supported by viewer]
stage1
stage1
Builds
Builds
stage1
stage1
Outputs
Outputs
libstd
libstd
Copy
Copy
stage1-std
stage1-std
stage1/lib/rustlib
stage1/lib/rustlib
Builds
Builds
stage1
stage1
Outputs
Outputs
libtest
libtest
Copy
Copy
stage1-test
stage1-test
stage1/lib/rustlib
stage1/lib/rustlib
Builds
Builds
stage1
stage1
Outputs
Outputs
rustc
rustc
Copy
Copy
stage1-rustc
stage1-rustc
stage1/lib/rustlib
stage1/lib/rustlib
Builds
Builds
stage1
stage1
Outputs
Outputs
codegen
codegen
stage1-codegen
stage1-codegen
Stage 1
[Not supported by viewer]
Copy
Copy
stage1-rustc
stage1-codegen
stage1/lib/rustlib
[Not supported by viewer]
stage2
stage2
Builds
Builds
stage2
stage2
Outputs
Outputs
rustdoc
rustdoc
Copy
[Not supported by viewer]
stage2-tools
stage2-tools
Builds
Builds
stage0
stage0
bootstrap
bootstrap
llvm
llvm
stage2
stage2
Stage 2
[Not supported by viewer]
\ No newline at end of file diff --git a/src/doc/rustc-guide/src/implementing_new_features.md b/src/doc/rustc-guide/src/implementing_new_features.md index 8105e1474a..6d1327fabb 100644 --- a/src/doc/rustc-guide/src/implementing_new_features.md +++ b/src/doc/rustc-guide/src/implementing_new_features.md @@ -49,7 +49,7 @@ In some cases, a feature or bugfix might break some existing programs in some edge cases. In that case, you might want to do a crater run to assess the impact and possibly add a future-compatibility lint, similar to those used for -[edition-gated lints](./diag.md#edition-gated-lints). +[edition-gated lints](diagnostics.md#edition-gated-lints). ### Stability diff --git a/src/doc/rustc-guide/src/mir/visitor.md b/src/doc/rustc-guide/src/mir/visitor.md index ad00bc3f16..a5e8e9a0b6 100644 --- a/src/doc/rustc-guide/src/mir/visitor.md +++ b/src/doc/rustc-guide/src/mir/visitor.md @@ -15,7 +15,7 @@ state you will need while processing MIR: ```rust,ignore struct MyVisitor<...> { - tcx: TyCtxt<'cx, 'tcx, 'tcx>, + tcx: TyCtxt<'tcx>, ... } ``` diff --git a/src/doc/rustc-guide/src/profile-guided-optimization.md b/src/doc/rustc-guide/src/profile-guided-optimization.md new file mode 100644 index 0000000000..fb897e901e --- /dev/null +++ b/src/doc/rustc-guide/src/profile-guided-optimization.md @@ -0,0 +1,132 @@ +# Profile Guided Optimization + +`rustc` supports doing profile-guided optimization (PGO). +This chapter describes what PGO is and how the support for it is +implemented in `rustc`. + +## What Is Profiled-Guided Optimization? + +The basic concept of PGO is to collect data about the typical execution of +a program (e.g. which branches it is likely to take) and then use this data +to inform optimizations such as inlining, machine-code layout, +register allocation, etc. + +There are different ways of collecting data about a program's execution. +One is to run the program inside a profiler (such as `perf`) and another +is to create an instrumented binary, that is, a binary that has data +collection built into it, and run that. +The latter usually provides more accurate data. + +## How is PGO implemented in `rustc`? + +`rustc` current PGO implementation relies entirely on LLVM. +LLVM actually [supports multiple forms][clang-pgo] of PGO: + +[clang-pgo]: https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization + +- Sampling-based PGO where an external profiling tool like `perf` is used + to collect data about a program's execution. +- GCOV-based profiling, where code coverage infrastructure is used to collect + profiling information. +- Front-end based instrumentation, where the compiler front-end (e.g. Clang) + inserts instrumentation intrinsics into the LLVM IR it generates. +- IR-level instrumentation, where LLVM inserts the instrumentation intrinsics + itself during optimization passes. + +`rustc` supports only the last approach, IR-level instrumentation, mainly +because it is almost exclusively implemented in LLVM and needs little +maintenance on the Rust side. Fortunately, it is also the most modern approach, +yielding the best results. + +So, we are dealing with an instrumentation-based approach, i.e. profiling data +is generated by a specially instrumented version of the program that's being +optimized. Instrumentation-based PGO has two components: a compile-time +component and run-time component, and one needs to understand the overall +workflow to see how they interact. + +### Overall Workflow + +Generating a PGO-optimized program involves the following four steps: + +1. Compile the program with instrumentation enabled (e.g. `rustc -Cprofile-generate main.rs`) +2. Run the instrumented program (e.g. `./main`) which generates a `default-.profraw` file +3. Convert the `.profraw` file into a `.profdata` file using LLVM's `llvm-profdata` tool. +4. Compile the program again, this time making use of the profiling data + (e.g. `rustc -Cprofile-use=merged.profdata main.rs`) + +### Compile-Time Aspects + +Depending on which step in the above workflow we are in, two different things +can happen at compile time: + +#### Create Binaries with Instrumentation + +As mentioned above, the profiling instrumentation is added by LLVM. +`rustc` instructs LLVM to do so [by setting the appropriate][pgo-gen-passmanager] +flags when creating LLVM `PassManager`s: + +```C + // `PMBR` is an `LLVMPassManagerBuilderRef` + unwrap(PMBR)->EnablePGOInstrGen = true; + // Instrumented binaries have a default output path for the `.profraw` file + // hard-coded into them: + unwrap(PMBR)->PGOInstrGen = PGOGenPath; +``` + +`rustc` also has to make sure that some of the symbols from LLVM's profiling +runtime are not removed [by marking the with the right export level][pgo-gen-symbols]. + +[pgo-gen-passmanager]: https://github.com/rust-lang/rust/blob/1.34.1/src/rustllvm/PassWrapper.cpp#L412-L416 +[pgo-gen-symbols]:https://github.com/rust-lang/rust/blob/1.34.1/src/librustc_codegen_ssa/back/symbol_export.rs#L212-L225 + + +#### Compile Binaries Where Optimizations Make Use Of Profiling Data + +In the final step of the workflow described above, the program is compiled +again, with the compiler using the gathered profiling data in order to drive +optimization decisions. `rustc` again leaves most of the work to LLVM here, +basically [just telling][pgo-use-passmanager] the LLVM `PassManagerBuilder` +where the profiling data can be found: + +```C + unwrap(PMBR)->PGOInstrUse = PGOUsePath; +``` + +[pgo-use-passmanager]: https://github.com/rust-lang/rust/blob/1.34.1/src/rustllvm/PassWrapper.cpp#L417-L420 + +LLVM does the rest (e.g. setting branch weights, marking functions with +`cold` or `inlinehint`, etc). + + +### Runtime Aspects + +Instrumentation-based approaches always also have a runtime component, i.e. +once we have an instrumented program, that program needs to be run in order +to generate profiling data, and collecting and persisting this profiling +data needs some infrastructure in place. + +In the case of LLVM, these runtime components are implemented in +[compiler-rt][compiler-rt-profile] and statically linked into any instrumented +binaries. +The `rustc` version of this can be found in `src/libprofiler_builtins` which +basically packs the C code from `compiler-rt` into a Rust crate. + +In order for `libprofiler_builtins` to be built, `profiler = true` must be set +in `rustc`'s `config.toml`. + +[compiler-rt-profile]: https://github.com/llvm/llvm-project/tree/master/compiler-rt/lib/profile + +## Testing PGO + +Since the PGO workflow spans multiple compiler invocations most testing happens +in [run-make tests][rmake-tests] (the relevant tests have `pgo` in their name). +There is also a [codegen test][codegen-test] that checks that some expected +instrumentation artifacts show up in LLVM IR. + +[rmake-tests]: https://github.com/rust-lang/rust/tree/master/src/test/run-make-fulldeps +[codegen-test]: https://github.com/rust-lang/rust/blob/master/src/test/codegen/pgo-instrumentation.rs + +## Additional Information + +Clang's documentation contains a good overview on PGO in LLVM here: +https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization diff --git a/src/doc/rustc-guide/src/profiling/with_perf.md b/src/doc/rustc-guide/src/profiling/with_perf.md index 2588994002..7582eece56 100644 --- a/src/doc/rustc-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-guide/src/profiling/with_perf.md @@ -7,15 +7,15 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or - Get a clean checkout of rust-lang/master, or whatever it is you want to profile. - Set the following settings in your `config.toml`: - - `debuginfo-lines = true` - - `use-jemalloc = false` — lets you do memory use profiling with valgrind + - `debuginfo-level = 1` - enables line debuginfo + - `use-jemalloc = false` - lets you do memory use profiling with valgrind - leave everything else the defaults - Run `./x.py build` to get a full build - Make a rustup toolchain pointing to that result - see [the "build and run" section for instructions][b-a-r] [b-a-r]: ../how-to-build-and-run.html#toolchain - + ## Gathering a perf profile perf is an excellent tool on linux that can be used to gather and @@ -272,9 +272,9 @@ Tree : : | rustc_mir::borrow_check::nll::type_check::type_check_internal (13% total, 0% self) : : : | core::ops::function::FnOnce::call_once (5% total, 0% self) : : : : | rustc_mir::borrow_check::nll::type_check::liveness::generate (5% total, 3% self) -: : : | as rustc::mir::visit::Visitor<'tcx>>::visit_mir (3% total, 0% self) +: : : | as rustc::mir::visit::Visitor<'tcx>>::visit_mir (3% total, 0% self) : | rustc::mir::visit::Visitor::visit_mir (8% total, 6% self) -: | as rustc_mir::dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (5% total, 0% self) +: | as rustc_mir::dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (5% total, 0% self) : | rustc_mir::dataflow::do_dataflow (3% total, 0% self) ``` @@ -295,7 +295,7 @@ altogether ("total") and the percent of time spent in **just that function and not some callee of that function** (self). Usually "total" is the more interesting number, but not always. -### Relative percentages +### Relative percentages By default, all in perf-focus are relative to the **total program execution**. This is useful to help you keep perspective — often as @@ -321,7 +321,7 @@ Tree | matched `{do_mir_borrowck}` (100% total, 0% self) : | rustc_mir::borrow_check::nll::compute_regions (47% total, 0% self) [...] : | rustc::mir::visit::Visitor::visit_mir (19% total, 15% self) [...] -: | as rustc_mir::dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (13% total, 0% self) [...] +: | as rustc_mir::dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (13% total, 0% self) [...] : | rustc_mir::dataflow::do_dataflow (8% total, 1% self) [...] ``` diff --git a/src/doc/rustc-guide/src/queries/query-evaluation-model-in-detail.md b/src/doc/rustc-guide/src/queries/query-evaluation-model-in-detail.md index 47412acef7..7772f36bea 100644 --- a/src/doc/rustc-guide/src/queries/query-evaluation-model-in-detail.md +++ b/src/doc/rustc-guide/src/queries/query-evaluation-model-in-detail.md @@ -204,7 +204,7 @@ OK as long as the mutation is not observable. This is achieved by two things: This is not an ideal setup because of the manual intervention needed, so it should be used sparingly and only when it is well known which queries might access a given result. In practice, however, stealing has not turned out to be -much of a maintainance burden. +much of a maintenance burden. To summarize: "Steal queries" break some of the rules in a controlled way. There are checks in place that make sure that nothing can go silently wrong. diff --git a/src/doc/rustc-guide/src/query.md b/src/doc/rustc-guide/src/query.md index 4d80187aae..4ab1d079ec 100644 --- a/src/doc/rustc-guide/src/query.md +++ b/src/doc/rustc-guide/src/query.md @@ -82,17 +82,15 @@ on how that works). Providers always have the same signature: ```rust,ignore -fn provider<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx, 'tcx>, - key: QUERY_KEY) - -> QUERY_RESULT -{ +fn provider<'tcx>( + tcx: TyCtxt<'tcx>, + key: QUERY_KEY, +) -> QUERY_RESULT { ... } ``` -Providers take two arguments: the `tcx` and the query key. Note also -that they take the *global* tcx (i.e. they use the `'tcx` lifetime -twice), rather than taking a tcx with some active inference context. +Providers take two arguments: the `tcx` and the query key. They return the result of the query. #### How providers are setup @@ -103,7 +101,7 @@ is basically a big list of function pointers: ```rust,ignore struct Providers { - type_of: for<'cx, 'tcx> fn(TyCtxt<'cx, 'tcx, 'tcx>, DefId) -> Ty<'tcx>, + type_of: for<'tcx> fn(TyCtxt<'tcx>, DefId) -> Ty<'tcx>, ... } ``` @@ -144,7 +142,7 @@ pub fn provide(providers: &mut Providers) { }; } -fn fubar<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>, key: DefId) -> Fubar<'tcx> { ... } +fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... } ``` N.B. Most of the `rustc_*` crates only provide **local diff --git a/src/doc/rustc-guide/src/stabilization_guide.md b/src/doc/rustc-guide/src/stabilization_guide.md index 56da5cdaf1..76446150c4 100644 --- a/src/doc/rustc-guide/src/stabilization_guide.md +++ b/src/doc/rustc-guide/src/stabilization_guide.md @@ -125,7 +125,7 @@ writing, the next stable release (i.e. what is currently beta) was Next search for the feature string (in this case, `pub_restricted`) in the codebase to find where it appears. Change uses of `#![feature(XXX)]` from the `libstd` and any rustc crates to be -`#![cfg_attr(stage0, feature(XXX))]`. This includes the feature-gate +`#![cfg_attr(bootstrap, feature(XXX))]`. This includes the feature-gate only for stage0, which is built using the current beta (this is needed because the feature is still unstable in the current beta). diff --git a/src/doc/rustc-guide/src/tests/running.md b/src/doc/rustc-guide/src/tests/running.md index 1250fa77b7..5a05c156f9 100644 --- a/src/doc/rustc-guide/src/tests/running.md +++ b/src/doc/rustc-guide/src/tests/running.md @@ -47,6 +47,19 @@ the debuginfo test suite: > ./x.py test --stage 1 src/test/debuginfo ``` +If you only need to test a specific subdirectory of tests for any +given test suite, you can pass that directory to `x.py test`: + +```bash +> ./x.py test --stage 1 src/test/ui/const-generics +``` + +Likewise, you can test a single file by passing its path: + +```bash +> ./x.py test --stage 1 src/test/ui/const-generics/const-test.rs +``` + ### Run only the tidy script ```bash @@ -82,8 +95,9 @@ work well with procedural macros or custom derive tests. ## Running an individual test Another common thing that people want to do is to run an **individual -test**, often the test they are trying to fix. One way to do this is -to invoke `x.py` with the `--test-args` option: +test**, often the test they are trying to fix. As mentioned earlier, +you may pass the full file path to achieve this, or alternatively one +may invoke `x.py` with the `--test-args` option: ```bash > ./x.py test --stage 1 src/test/ui --test-args issue-1234 @@ -91,7 +105,8 @@ to invoke `x.py` with the `--test-args` option: Under the hood, the test runner invokes the standard rust test runner (the same one you get with `#[test]`), so this command would wind up -filtering for tests that include "issue-1234" in the name. +filtering for tests that include "issue-1234" in the name. (Thus +`--test-args` is a good way to run a collection of related tests.) ## Using incremental compilation diff --git a/src/doc/rustc-guide/src/traits/chalk-overview.md b/src/doc/rustc-guide/src/traits/chalk-overview.md index 54f6c33949..0a95585f6d 100644 --- a/src/doc/rustc-guide/src/traits/chalk-overview.md +++ b/src/doc/rustc-guide/src/traits/chalk-overview.md @@ -126,10 +126,10 @@ things", chalk_ir defines [`ProgramEnvironment`] which is "pure logic". The main field in that struct is `program_clauses`, which contains the [`ProgramClause`]s generated by the rules module. -### Rules ([chalk_rules]) +### Rules ([chalk_solve]) -The `chalk_rules` crate ([source code][chalk_rules]) defines the logic rules we use -for each item in the Rust IR. It works by iterating over every trait, impl, +The `chalk_solve` crate ([source code][chalk_solve]) defines the logic rules we +use for each item in the Rust IR. It works by iterating over every trait, impl, etc. and emitting the rules that come from each one. *See also: [Lowering Rules][lowering-rules]* @@ -137,7 +137,7 @@ etc. and emitting the rules that come from each one. #### Well-formedness checks As part of lowering to logic, we also do some "well formedness" checks. See -the [`chalk_rules::wf` source code][rules-wf-src] for where those are done. +the [`chalk_solve::wf` source code][solve-wf-src] for where those are done. *See also: [Well-formedness checking][wf-checking]* @@ -163,12 +163,11 @@ Chalk's functionality is broken up into the following crates: - [**chalk_ir**][chalk_ir]: Defines chalk's internal representation of types, lifetimes, and goals. - [**chalk_solve**][chalk_solve]: Combines `chalk_ir` and `chalk_engine`, - effectively. + effectively, which implements logic rules converting `chalk_rust_ir` to + `chalk_ir` + - Defines the `coherence` module, which implements coherence rules - [`chalk_engine::context`][engine-context] provides the necessary hooks. - [**chalk_parse**][chalk_parse]: Defines the raw AST and a parser. -- [**chalk_rules**][chalk_rules]: which implements logic rules converting - `chalk_rust_ir` to `chalk_ir` - - Defines the `coherence` module, which implements coherence rules - [**chalk**][doc-chalk]: Brings everything together. Defines the following modules: - `chalk::lowering`, which converts AST to `chalk_rust_ir` @@ -236,7 +235,6 @@ Likewise, lowering tests use the [`lowering_success!` and [chalk_ir]: https://rust-lang.github.io/chalk/doc/chalk_ir/index.html [chalk_parse]: https://rust-lang.github.io/chalk/doc/chalk_parse/index.html [chalk_solve]: https://rust-lang.github.io/chalk/doc/chalk_solve/index.html -[chalk_rules]: https://rust-lang.github.io/chalk/doc/chalk_rules/index.html [chalk_rust_ir]: https://rust-lang.github.io/chalk/doc/chalk_rust_ir/index.html [doc-chalk]: https://rust-lang.github.io/chalk/doc/chalk/index.html [engine-context]: https://rust-lang.github.io/chalk/doc/chalk_engine/context/index.html @@ -250,9 +248,9 @@ Likewise, lowering tests use the [`lowering_success!` and [chalk-test-wf]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/rules/wf/test.rs#L1 [chalki]: https://rust-lang.github.io/chalk/doc/chalki/index.html [clause]: https://github.com/rust-lang/chalk/blob/master/GLOSSARY.md#clause -[coherence-src]: http://rust-lang.github.io/chalk/doc/chalk_rules/coherence/index.html +[coherence-src]: http://rust-lang.github.io/chalk/doc/chalk_solve/coherence/index.html [ir-code]: http://rust-lang.github.io/chalk/doc/chalk_rust_ir/ -[rules-wf-src]: http://rust-lang.github.io/chalk/doc/chalk_rules/wf/index.html +[solve-wf-src]: http://rust-lang.github.io/chalk/doc/chalk_solve/wf/index.html [solve_goal]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L85 [test-lowering-macros]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test_util.rs#L21-L54 [test-macro]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L33 diff --git a/src/doc/rustc-guide/src/traits/slg.md b/src/doc/rustc-guide/src/traits/slg.md index 98547575dc..948d3fc8ab 100644 --- a/src/doc/rustc-guide/src/traits/slg.md +++ b/src/doc/rustc-guide/src/traits/slg.md @@ -147,7 +147,7 @@ are both represented with an index.) For each strand, we also optionally store a *selected subgoal*. This is the subgoal after the turnstile (`:-`) that we are currently trying -to prove in this strand. Initally, when a strand is first created, +to prove in this strand. Initially, when a strand is first created, there is no selected subgoal. [`ExClause`]: https://rust-lang.github.io/chalk/doc/chalk_engine/struct.ExClause.html diff --git a/src/doc/rustc-guide/src/ty.md b/src/doc/rustc-guide/src/ty.md index d9979bc0b4..72405d2971 100644 --- a/src/doc/rustc-guide/src/ty.md +++ b/src/doc/rustc-guide/src/ty.md @@ -11,63 +11,19 @@ compiler. It is the context that you use to perform all manner of queries. The struct `TyCtxt` defines a reference to this shared context: ```rust,ignore -tcx: TyCtxt<'a, 'gcx, 'tcx> -// -- ---- ---- -// | | | -// | | innermost arena lifetime (if any) -// | "global arena" lifetime -// lifetime of this reference +tcx: TyCtxt<'tcx> +// ---- +// | +// arena lifetime ``` -As you can see, the `TyCtxt` type takes three lifetime parameters. -These lifetimes are perhaps the most complex thing to understand about -the tcx. During Rust compilation, we allocate most of our memory in +As you can see, the `TyCtxt` type takes a lifetime parameter. +During Rust compilation, we allocate most of our memory in **arenas**, which are basically pools of memory that get freed all at -once. When you see a reference with a lifetime like `'tcx` or `'gcx`, +once. When you see a reference with a lifetime like `'tcx`, you know that it refers to arena-allocated data (or data that lives as long as the arenas, anyhow). -We use two distinct levels of arenas. The outer level is the "global -arena". This arena lasts for the entire compilation: so anything you -allocate in there is only freed once compilation is basically over -(actually, when we shift to executing LLVM). - -To reduce peak memory usage, when we do type inference, we also use an -inner level of arena. These arenas get thrown away once type inference -is over. This is done because type inference generates a lot of -"throw-away" types that are not particularly interesting after type -inference completes, so keeping around those allocations would be -wasteful. - -Often, we wish to write code that explicitly asserts that it is not -taking place during inference. In that case, there is no "local" -arena, and all the types that you can access are allocated in the -global arena. To express this, the idea is to use the same lifetime -for the `'gcx` and `'tcx` parameters of `TyCtxt`. Just to be a touch -confusing, we tend to use the name `'tcx` in such contexts. Here is an -example: - -```rust,ignore -fn not_in_inference<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { - // ---- ---- - // Using the same lifetime here asserts - // that the innermost arena accessible through - // this reference *is* the global arena. -} -``` - -In contrast, if we want to code that can be usable during type inference, then -you need to declare a distinct `'gcx` and `'tcx` lifetime parameter: - -```rust,ignore -fn maybe_in_inference<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) { - // ---- ---- - // Using different lifetimes here means that - // the innermost arena *may* be distinct - // from the global arena (but doesn't have to be). -} -``` - ### Allocating and working with types Rust types are represented using the `Ty<'tcx>` defined in the `ty` diff --git a/src/doc/rustc-guide/src/type-inference.md b/src/doc/rustc-guide/src/type-inference.md index a3d012b5df..d4734525f7 100644 --- a/src/doc/rustc-guide/src/type-inference.md +++ b/src/doc/rustc-guide/src/type-inference.md @@ -6,14 +6,14 @@ expression. It is what allows Rust to work with fewer or no type annotations, making things easier for users: -```rust,ignore +```rust fn main() { let mut things = vec![]; - things.push("thing") + things.push("thing"); } ``` -Here, the type of `things` is *inferenced* to be `&str` because that's the value +Here, the type of `things` is *inferred* to be `Vec<&str>` because of the value we push into `things`. The type inference is based on the standard Hindley-Milner (HM) type inference @@ -50,9 +50,8 @@ function and disposed of after it returns. [ty-ch]: ty.html -Within the closure, `infcx` has the type `InferCtxt<'cx, 'gcx, 'tcx>` -for some fresh `'cx` and `'tcx` – the latter corresponds to the lifetime of -this temporary arena, and the `'cx` is the lifetime of the `InferCtxt` itself. +Within the closure, `infcx` has the type `InferCtxt<'cx, 'tcx>` for some +fresh `'cx`, while `'tcx` is the same as outside the inference context. (Again, see the [`ty` chapter][ty-ch] for more details on this setup.) The `tcx.infer_ctxt` method actually returns a builder, which means diff --git a/src/doc/rustc-guide/triagebot.toml b/src/doc/rustc-guide/triagebot.toml new file mode 100644 index 0000000000..fa0824ac53 --- /dev/null +++ b/src/doc/rustc-guide/triagebot.toml @@ -0,0 +1 @@ +[assign] diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 34708d1847..3cda8d9279 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -13,5 +13,6 @@ - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) - [Custom Targets](targets/custom.md) +- [Profile-guided Optimization](profile-guided-optimization.md) - [Linker-plugin based LTO](linker-plugin-lto.md) - [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index a616409d9a..3773a77830 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -214,3 +214,20 @@ This option lets you control what happens when the code panics. ## incremental This flag allows you to enable incremental compilation. + +## profile-generate + +This flag allows for creating instrumented binaries that will collect +profiling data for use with profile-guided optimization (PGO). The flag takes +an optional argument which is the path to a directory into which the +instrumented binary will emit the collected data. See the chapter on +[profile-guided optimization](profile-guided-optimization.html) for more +information. + +## profile-use + +This flag specifies the profiling data file to be used for profile-guided +optimization (PGO). The flag takes a mandatory argument which is the path +to a valid `.profdata` file. See the chapter on +[profile-guided optimization](profile-guided-optimization.html) for more +information. diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 73a2efcb33..2ae726c4ba 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -100,9 +100,10 @@ LLVM. However, the approximation is usually reliable. The following table shows known good combinations of toolchain versions. -| | Clang 7 | Clang 8 | +| | Clang 7 | Clang 8 | |-----------|-----------|-----------| | Rust 1.34 | ✗ | ✓ | -| Rust 1.35 | ✗ | ✓(?) | +| Rust 1.35 | ✗ | ✓ | +| Rust 1.36 | ✗ | ✓ | Note that the compatibility policy for this feature might change in the future. diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index ba927b1ef3..6d4aa024c7 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -529,18 +529,21 @@ This lint detects bounds in type aliases. These are not currently enforced. Some example code that triggers this lint: ```rust +#[allow(dead_code)] type SendVec = Vec; ``` This will produce: ```text -warning: type alias is never used: `SendVec` - --> src/main.rs:1:1 +warning: bounds on generic parameters are not enforced in type aliases + --> src/lib.rs:2:17 | -1 | type SendVec = Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +2 | type SendVec = Vec; + | ^^^^ | + = note: #[warn(type_alias_bounds)] on by default + = help: the bound will not be checked when the type alias is used, and should be removed ``` ## tyvar-behind-raw-pointer @@ -725,19 +728,17 @@ This lint detects attributes that were not used by the compiler. Some example code that triggers this lint: ```rust -#![feature(custom_attribute)] - -#![mutable_doc] +#![macro_export] ``` This will produce: ```text warning: unused attribute - --> src/main.rs:4:1 + --> src/main.rs:1:1 | -4 | #![mutable_doc] - | ^^^^^^^^^^^^^^^ +1 | #![macro_export] + | ^^^^^^^^^^^^^^^^ | ``` diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md new file mode 100644 index 0000000000..38be07a644 --- /dev/null +++ b/src/doc/rustc/src/profile-guided-optimization.md @@ -0,0 +1,136 @@ +# Profile Guided Optimization + +`rustc` supports doing profile-guided optimization (PGO). +This chapter describes what PGO is, what it is good for, and how it can be used. + +## What Is Profiled-Guided Optimization? + +The basic concept of PGO is to collect data about the typical execution of +a program (e.g. which branches it is likely to take) and then use this data +to inform optimizations such as inlining, machine-code layout, +register allocation, etc. + +There are different ways of collecting data about a program's execution. +One is to run the program inside a profiler (such as `perf`) and another +is to create an instrumented binary, that is, a binary that has data +collection built into it, and run that. +The latter usually provides more accurate data and it is also what is +supported by `rustc`. + +## Usage + +Generating a PGO-optimized program involves following a workflow with four steps: + +1. Compile the program with instrumentation enabled + (e.g. `rustc -Cprofile-generate=/tmp/pgo-data main.rs`) +2. Run the instrumented program (e.g. `./main`) which generates a + `default_.profraw` file +3. Convert the `.profraw` file into a `.profdata` file using + LLVM's `llvm-profdata` tool +4. Compile the program again, this time making use of the profiling data + (for example `rustc -Cprofile-use=merged.profdata main.rs`) + +An instrumented program will create one or more `.profraw` files, one for each +instrumented binary. E.g. an instrumented executable that loads two instrumented +dynamic libraries at runtime will generate three `.profraw` files. Running an +instrumented binary multiple times, on the other hand, will re-use the +respective `.profraw` files, updating them in place. + +These `.profraw` files have to be post-processed before they can be fed back +into the compiler. This is done by the `llvm-profdata` tool. This tool +is most easily installed via + +```bash +rustup component add llvm-tools-preview +``` + +Note that installing the `llvm-tools-preview` component won't add +`llvm-profdata` to the `PATH`. Rather, the tool can be found in: + +```bash +~/.rustup/toolchains//lib/rustlib//bin/ +``` + +Alternatively, an `llvm-profdata` coming with a recent LLVM or Clang +version usually works too. + +The `llvm-profdata` tool merges multiple `.profraw` files into a single +`.profdata` file that can then be fed back into the compiler via +`-Cprofile-use`: + +```bash +# STEP 1: Compile the binary with instrumentation +rustc -Cprofile-generate=/tmp/pgo-data -O ./main.rs + +# STEP 2: Run the binary a few times, maybe with common sets of args. +# Each run will create or update `.profraw` files in /tmp/pgo-data +./main mydata1.csv +./main mydata2.csv +./main mydata3.csv + +# STEP 3: Merge and post-process all the `.profraw` files in /tmp/pgo-data +llvm-profdata merge -o ./merged.profdata /tmp/pgo-data + +# STEP 4: Use the merged `.profdata` file during optimization. All `rustc` +# flags have to be the same. +rustc -Cprofile-use=./merged.profdata -O ./main.rs +``` + +### A Complete Cargo Workflow + +Using this feature with Cargo works very similar to using it with `rustc` +directly. Again, we generate an instrumented binary, run it to produce data, +merge the data, and feed it back into the compiler. Some things of note: + +- We use the `RUSTFLAGS` environment variable in order to pass the PGO compiler + flags to the compilation of all crates in the program. + +- We pass the `--target` flag to Cargo, which prevents the `RUSTFLAGS` + arguments to be passed to Cargo build scripts. We don't want the build + scripts to generate a bunch of `.profraw` files. + +- We pass `--release` to Cargo because that's where PGO makes the most sense. + In theory, PGO can also be done on debug builds but there is little reason + to do so. + +- It is recommended to use *absolute paths* for the argument of + `-Cprofile-generate` and `-Cprofile-use`. Cargo can invoke `rustc` with + varying working directories, meaning that `rustc` will not be able to find + the supplied `.profdata` file. With absolute paths this is not an issue. + +- It is good practice to make sure that there is no left-over profiling data + from previous compilation sessions. Just deleting the directory is a simple + way of doing so (see `STEP 0` below). + +This is what the entire workflow looks like: + +```bash +# STEP 0: Make sure there is no left-over profiling data from previous runs +rm -rf /tmp/pgo-data + +# STEP 1: Build the instrumented binaries +RUSTFLAGS="-Cprofile-generate=/tmp/pgo-data" \ + cargo build --release --target=x86_64-unknown-linux-gnu + +# STEP 2: Run the instrumented binaries with some typical data +./target/x86_64-unknown-linux-gnu/release/myprogram mydata1.csv +./target/x86_64-unknown-linux-gnu/release/myprogram mydata2.csv +./target/x86_64-unknown-linux-gnu/release/myprogram mydata3.csv + +# STEP 3: Merge the `.profraw` files into a `.profdata` file +llvm-profdata merge -o /tmp/pgo-data/merged.profdata /tmp/pgo-data + +# STEP 4: Use the `.profdata` file for guiding optimizations +RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata" \ + cargo build --release --target=x86_64-unknown-linux-gnu +``` + +## Further Reading + +`rustc`'s PGO support relies entirely on LLVM's implementation of the feature +and is equivalent to what Clang offers via the `-fprofile-generate` / +`-fprofile-use` flags. The [Profile Guided Optimization][clang-pgo] section +in Clang's documentation is therefore an interesting read for anyone who wants +to use PGO with Rust. + +[clang-pgo]: https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index aba485f752..b21defaedc 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -178,7 +178,7 @@ $ rustdoc src/lib.rs --passes strip-priv-imports An argument of "list" will print a list of possible "rustdoc passes", and other arguments will be the name of which passes to run in addition to the defaults. -For more details on passes, see [the chapter on them](passes.html). +For more details on passes, see [the chapter on them](passes.md). See also `--no-defaults`. @@ -194,7 +194,7 @@ By default, `rustdoc` will run several passes over your code. This removes those defaults, allowing you to use `--passes` to specify exactly which passes you want. -For more details on passes, see [the chapter on them](passes.html). +For more details on passes, see [the chapter on them](passes.md). See also `--passes`. @@ -207,7 +207,7 @@ $ rustdoc src/lib.rs --test ``` This flag will run your code examples as tests. For more, see [the chapter -on documentation tests](documentation-tests.html). +on documentation tests](documentation-tests.md). See also `--test-args`. @@ -220,7 +220,7 @@ $ rustdoc src/lib.rs --test --test-args ignored ``` This flag will pass options to the test runner when running documentation tests. -For more, see [the chapter on documentation tests](documentation-tests.html). +For more, see [the chapter on documentation tests](documentation-tests.md). See also `--test`. diff --git a/src/doc/rustdoc/src/passes.md b/src/doc/rustdoc/src/passes.md index 615b3dca19..12d4ea205b 100644 --- a/src/doc/rustdoc/src/passes.md +++ b/src/doc/rustdoc/src/passes.md @@ -5,8 +5,8 @@ Rustdoc has a concept called "passes". These are transformations that In addition to the passes below, check out the docs for these flags: -* [`--passes`](command-line-arguments.html#a--passes-add-more-rustdoc-passes) -* [`--no-defaults`](command-line-arguments.html#a--no-defaults-dont-run-default-passes) +* [`--passes`](command-line-arguments.md#--passes-add-more-rustdoc-passes) +* [`--no-defaults`](command-line-arguments.md#--no-defaults-dont-run-default-passes) ## Default passes diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md index b165c5a6b3..80ac405eb2 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/the-doc-attribute.md @@ -202,7 +202,7 @@ mod bar { Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere. One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will -not eagerly inline it as a module unless you add `#[doc(inline)}`. +not eagerly inline it as a module unless you add `#[doc(inline)]`. ## `#[doc(hidden)]` diff --git a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md new file mode 100644 index 0000000000..e0bb782270 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md @@ -0,0 +1,37 @@ +# `arbitrary_enum_discriminant` + +The tracking issue for this feature is: [#60553] + +[#60553]: https://github.com/rust-lang/rust/issues/60553 + +------------------------ + +The `arbitrary_enum_discriminant` feature permits tuple-like and +struct-like enum variants with `#[repr()]` to have explicit discriminants. + +## Examples + +```rust +#![feature(arbitrary_enum_discriminant)] + +#[allow(dead_code)] +#[repr(u8)] +enum Enum { + Unit = 3, + Tuple(u16) = 2, + Struct { + a: u8, + b: u16, + } = 1, +} + +impl Enum { + fn tag(&self) -> u8 { + unsafe { *(self as *const Self as *const u8) } + } +} + +assert_eq!(3, Enum::Unit.tag()); +assert_eq!(2, Enum::Tuple(5).tag()); +assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); +``` diff --git a/src/doc/unstable-book/src/language-features/asm.md b/src/doc/unstable-book/src/language-features/asm.md index f22095fe5d..2a1b639778 100644 --- a/src/doc/unstable-book/src/language-features/asm.md +++ b/src/doc/unstable-book/src/language-features/asm.md @@ -190,4 +190,4 @@ constraints, etc. [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions If you need more power and don't mind losing some of the niceties of -`asm!`, check out [global_asm](language-features/global-asm.html). +`asm!`, check out [global_asm](global-asm.md). diff --git a/src/doc/unstable-book/src/language-features/box-patterns.md b/src/doc/unstable-book/src/language-features/box-patterns.md index 0896627aca..bf0819ec92 100644 --- a/src/doc/unstable-book/src/language-features/box-patterns.md +++ b/src/doc/unstable-book/src/language-features/box-patterns.md @@ -4,7 +4,7 @@ The tracking issue for this feature is: [#29641] [#29641]: https://github.com/rust-lang/rust/issues/29641 -See also [`box_syntax`](language-features/box-syntax.html) +See also [`box_syntax`](box-syntax.md) ------------------------ diff --git a/src/doc/unstable-book/src/language-features/box-syntax.md b/src/doc/unstable-book/src/language-features/box-syntax.md index 414dc48e55..9569974d22 100644 --- a/src/doc/unstable-book/src/language-features/box-syntax.md +++ b/src/doc/unstable-book/src/language-features/box-syntax.md @@ -4,7 +4,7 @@ The tracking issue for this feature is: [#49733] [#49733]: https://github.com/rust-lang/rust/issues/49733 -See also [`box_patterns`](language-features/box-patterns.html) +See also [`box_patterns`](box-patterns.md) ------------------------ diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md index 426fc01a6b..97cf58e57e 100644 --- a/src/doc/unstable-book/src/language-features/generators.md +++ b/src/doc/unstable-book/src/language-features/generators.md @@ -146,7 +146,7 @@ closure-like semantics. Namely: generators also depend on variables live across suspension points. This means that although the ambient environment may be `Send` or `Sync`, the generator itself may not be due to internal variables live across `yield` points being - not-`Send` or not-`Sync`. Note that generators, like closures, do + not-`Send` or not-`Sync`. Note that generators do not implement traits like `Copy` or `Clone` automatically. * Whenever a generator is dropped it will drop all captured environment diff --git a/src/doc/unstable-book/src/language-features/global-asm.md b/src/doc/unstable-book/src/language-features/global-asm.md index f1ef74a63b..bc55fe80fa 100644 --- a/src/doc/unstable-book/src/language-features/global-asm.md +++ b/src/doc/unstable-book/src/language-features/global-asm.md @@ -75,4 +75,4 @@ usages and placed the larger, single usage in the crate root. If you don't need quite as much power and flexibility as `global_asm!` provides, and you don't mind restricting your inline assembly to `fn` bodies only, you might try the -[asm](language-features/asm.html) feature instead. +[asm](asm.md) feature instead. diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index b16739b474..3ee024c6b5 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -192,7 +192,7 @@ such as "```undefined reference to `__rust_probestack'```". Using this crate also requires enabling the library feature `compiler_builtins_lib`. You can read more about this [here][compiler-builtins-lib]. -[compiler-builtins-lib]: library-features/compiler-builtins-lib.html +[compiler-builtins-lib]: ../library-features/compiler-builtins-lib.md ## More about the language items diff --git a/src/doc/unstable-book/src/language-features/member-constraints.md b/src/doc/unstable-book/src/language-features/member-constraints.md new file mode 100644 index 0000000000..0d11c31aca --- /dev/null +++ b/src/doc/unstable-book/src/language-features/member-constraints.md @@ -0,0 +1,29 @@ +# `member_constraints` + +The tracking issue for this feature is: [#61977] + +[#61977]: https://github.com/rust-lang/rust/issues/61977 + +------------------------ + +The `member_constraints` feature gate lets you use `impl Trait` syntax with +multiple unrelated lifetime parameters. + +A simple example is: + +```rust +#![feature(member_constraints)] + +trait Trait<'a, 'b> { } +impl Trait<'_, '_> for T {} + +fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> { + (x, y) +} + +fn main() { } +``` + +Without the `member_constraints` feature gate, the above example is an +error because both `'a` and `'b` appear in the impl Trait bounds, but +neither outlives the other. diff --git a/src/doc/unstable-book/src/language-features/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md index 46957c00bf..22dae0c89a 100644 --- a/src/doc/unstable-book/src/language-features/non-ascii-idents.md +++ b/src/doc/unstable-book/src/language-features/non-ascii-idents.md @@ -45,4 +45,4 @@ that does _not_ occur in the set of [strict keywords]. [`XID_start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i= [`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i= -[strict keywords]: ../reference/keywords.html#strict-keywords +[strict keywords]: ../../reference/keywords.md#strict-keywords diff --git a/src/doc/unstable-book/src/language-features/plugin-registrar.md b/src/doc/unstable-book/src/language-features/plugin-registrar.md index b16e2ac2d2..bf5dd81d73 100644 --- a/src/doc/unstable-book/src/language-features/plugin-registrar.md +++ b/src/doc/unstable-book/src/language-features/plugin-registrar.md @@ -8,6 +8,6 @@ This feature is part of "compiler plugins." It will often be used with the [`plugin`] and `rustc_private` features as well. For more details, see their docs. -[`plugin`]: language-features/plugin.html +[`plugin`]: plugin.md ------------------------ diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 49fe7c9e99..0e38e2865d 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -8,7 +8,7 @@ The tracking issue for this feature is: [#29597] This feature is part of "compiler plugins." It will often be used with the [`plugin_registrar`] and `rustc_private` features. -[`plugin_registrar`]: language-features/plugin-registrar.html +[`plugin_registrar`]: plugin-registrar.md ------------------------ @@ -39,7 +39,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](../book/macros.html), but the expansion is performed by arbitrary Rust +macros](../../book/macros.md), but the expansion is performed by arbitrary Rust code that manipulates syntax trees at compile time. @@ -56,7 +56,7 @@ extern crate syntax_pos; extern crate rustc; extern crate rustc_plugin; -use syntax::parse::token; +use syntax::parse::token::{self, Token}; use syntax::tokenstream::TokenTree; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; // A trait for expr_usize. @@ -64,7 +64,7 @@ use syntax_pos::Span; use rustc_plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) - -> Box { + -> Box { static NUMERALS: &'static [(&'static str, usize)] = &[ ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400), @@ -80,7 +80,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } let text = match args[0] { - TokenTree::Token(_, token::Ident(s)) => s.to_string(), + TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); return DummyResult::any(sp); @@ -130,9 +130,9 @@ The advantages over a simple `fn(&str) -> u32` are: a way to define new literal syntax for any data type. In addition to procedural macros, you can define new -[`derive`](../reference/attributes/derive.html)-like attributes and other kinds +[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds of extensions. See `Registry::register_syntax_extension` and the -`SyntaxExtension` enum. For a more involved macro example, see +`SyntaxExtension` struct. For a more involved macro example, see [`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). @@ -174,7 +174,7 @@ quasiquote as an ordinary plugin library. # Lint plugins Plugins can extend [Rust's lint -infrastructure](../reference/attributes/diagnostics.html#lint-check-attributes) with +infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with additional checks for code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs) that warns about any item named `lintme`. @@ -253,7 +253,7 @@ mostly use the same infrastructure as lint plugins, and provide examples of how to access type information. Lints defined by plugins are controlled by the usual [attributes and compiler -flags](../reference/attributes/diagnostics.html#lint-check-attributes), e.g. +flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g. `#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the first argument to `declare_lint!`, with appropriate case and punctuation conversion. diff --git a/src/doc/unstable-book/src/language-features/repr-align-enum.md b/src/doc/unstable-book/src/language-features/repr-align-enum.md deleted file mode 100644 index 415c6ebe8b..0000000000 --- a/src/doc/unstable-book/src/language-features/repr-align-enum.md +++ /dev/null @@ -1,42 +0,0 @@ -# `repr_align_enum` - -The tracking issue for this feature is: [#57996] - -[#57996]: https://github.com/rust-lang/rust/issues/57996 - ------------------------- - -The `repr_align_enum` feature allows using the `#[repr(align(x))]` attribute -on enums, similarly to structs. - -# Examples - -```rust -#![feature(repr_align_enum)] - -#[repr(align(8))] -enum Aligned { - Foo, - Bar { value: u32 }, -} - -fn main() { - assert_eq!(std::mem::align_of::(), 8); -} -``` - -This is equivalent to using an aligned wrapper struct everywhere: - -```rust -#[repr(align(8))] -struct Aligned(Unaligned); - -enum Unaligned { - Foo, - Bar { value: u32 }, -} - -fn main() { - assert_eq!(std::mem::align_of::(), 8); -} -``` diff --git a/src/doc/unstable-book/src/language-features/transparent-enums.md b/src/doc/unstable-book/src/language-features/transparent-enums.md new file mode 100644 index 0000000000..862411ab39 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/transparent-enums.md @@ -0,0 +1,93 @@ +# `transparent_enums` + +The tracking issue for this feature is [#60405] + +[60405]: https://github.com/rust-lang/rust/issues/60405 + +---- + +The `transparent_enums` feature allows you mark `enum`s as +`#[repr(transparent)]`. An `enum` may be `#[repr(transparent)]` if it has +exactly one variant, and that variant matches the same conditions which `struct` +requires for transparency. Some concrete illustrations follow. + +```rust +#![feature(transparent_enums)] + +// This enum has the same representation as `f32`. +#[repr(transparent)] +enum SingleFieldEnum { + Variant(f32) +} + +// This enum has the same representation as `usize`. +#[repr(transparent)] +enum MultiFieldEnum { + Variant { field: usize, nothing: () }, +} +``` + +For consistency with transparent `struct`s, `enum`s must have exactly one +non-zero-sized field. If all fields are zero-sized, the `enum` must not be +`#[repr(transparent)]`: + +```rust +#![feature(transparent_enums)] + +// This (non-transparent) enum is already valid in stable Rust: +pub enum GoodEnum { + Nothing, +} + +// Error: transparent enum needs exactly one non-zero-sized field, but has 0 +// #[repr(transparent)] +// pub enum BadEnum { +// Nothing(()), +// } + +// Error: transparent enum needs exactly one non-zero-sized field, but has 0 +// #[repr(transparent)] +// pub enum BadEmptyEnum { +// Nothing, +// } +``` + +The one exception is if the `enum` is generic over `T` and has a field of type +`T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type: + +```rust +#![feature(transparent_enums)] + +// This enum has the same representation as `T`. +#[repr(transparent)] +pub enum GenericEnum { + Variant(T, ()), +} + +// This is okay even though `()` is a zero-sized type. +pub const THIS_IS_OKAY: GenericEnum<()> = GenericEnum::Variant((), ()); +``` + +Transparent `enum`s require exactly one variant: + +```rust +// Error: transparent enum needs exactly one variant, but has 0 +// #[repr(transparent)] +// pub enum TooFewVariants { +// } + +// Error: transparent enum needs exactly one variant, but has 2 +// #[repr(transparent)] +// pub enum TooManyVariants { +// First(usize), +// Second, +// } +``` + +Like transarent `struct`s, a transparent `enum` of type `E` has the same layout, +size, and ABI as its single non-ZST field. If it is generic over a type `T`, and +all its fields are ZSTs except for exactly one field of type `T`, then it has +the same layout and ABI as `T` (even if `T` is a ZST when monomorphized). + +Like transparent `struct`s, transparent `enum`s are FFI-safe if and only if +their underlying representation type is also FFI-safe. diff --git a/src/doc/unstable-book/src/language-features/transparent-unions.md b/src/doc/unstable-book/src/language-features/transparent-unions.md new file mode 100644 index 0000000000..b731c9ea6d --- /dev/null +++ b/src/doc/unstable-book/src/language-features/transparent-unions.md @@ -0,0 +1,83 @@ +# `transparent_unions` + +The tracking issue for this feature is [#60405] + +[60405]: https://github.com/rust-lang/rust/issues/60405 + +---- + +The `transparent_unions` feature allows you mark `union`s as +`#[repr(transparent)]`. A `union` may be `#[repr(transparent)]` in exactly the +same conditions in which a `struct` may be `#[repr(transparent)]` (generally, +this means the `union` must have exactly one non-zero-sized field). Some +concrete illustrations follow. + +```rust +#![feature(transparent_unions)] + +// This union has the same representation as `f32`. +#[repr(transparent)] +union SingleFieldUnion { + field: f32, +} + +// This union has the same representation as `usize`. +#[repr(transparent)] +union MultiFieldUnion { + field: usize, + nothing: (), +} +``` + +For consistency with transparent `struct`s, `union`s must have exactly one +non-zero-sized field. If all fields are zero-sized, the `union` must not be +`#[repr(transparent)]`: + +```rust +#![feature(transparent_unions)] + +// This (non-transparent) union is already valid in stable Rust: +pub union GoodUnion { + pub nothing: (), +} + +// Error: transparent union needs exactly one non-zero-sized field, but has 0 +// #[repr(transparent)] +// pub union BadUnion { +// pub nothing: (), +// } +``` + +The one exception is if the `union` is generic over `T` and has a field of type +`T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type: + +```rust +#![feature(transparent_unions)] + +// This union has the same representation as `T`. +#[repr(transparent)] +pub union GenericUnion { // Unions with non-`Copy` fields are unstable. + pub field: T, + pub nothing: (), +} + +// This is okay even though `()` is a zero-sized type. +pub const THIS_IS_OKAY: GenericUnion<()> = GenericUnion { field: () }; +``` + +Like transarent `struct`s, a transparent `union` of type `U` has the same +layout, size, and ABI as its single non-ZST field. If it is generic over a type +`T`, and all its fields are ZSTs except for exactly one field of type `T`, then +it has the same layout and ABI as `T` (even if `T` is a ZST when monomorphized). + +Like transparent `struct`s, transparent `union`s are FFI-safe if and only if +their underlying representation type is also FFI-safe. + +A `union` may not be eligible for the same nonnull-style optimizations that a +`struct` or `enum` (with the same fields) are eligible for. Adding +`#[repr(transparent)]` to `union` does not change this. To give a more concrete +example, it is unspecified whether `size_of::()` is equal to +`size_of::>()`, where `T` is a `union` (regardless of whether or not +it is transparent). The Rust compiler is free to perform this optimization if +possible, but is not required to, and different compiler versions may differ in +their application of these optimizations. diff --git a/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md b/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md deleted file mode 100644 index bcdeafc4b1..0000000000 --- a/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md +++ /dev/null @@ -1,36 +0,0 @@ -# `type_alias_enum_variants` - -The tracking issue for this feature is: [#49683] - -[#49683]: https://github.com/rust-lang/rust/issues/49683 - ------------------------- - -The `type_alias_enum_variants` feature enables the use of variants on type -aliases that refer to enums, as both a constructor and a pattern. That is, -it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same -as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type -`Enum`). - -Note that since `Self` exists as a type alias, this feature also enables the -use of the syntax `Self::Variant` within an impl block for an enum type. - -```rust -#![feature(type_alias_enum_variants)] - -enum Foo { - Bar(i32), - Baz { i: i32 }, -} - -type Alias = Foo; - -fn main() { - let t = Alias::Bar(0); - let t = Alias::Baz { i: 0 }; - match t { - Alias::Bar(_i) => {} - Alias::Baz { i: _i } => {} - } -} -``` diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md index d845c99a88..71003fba00 100644 --- a/src/doc/unstable-book/src/language-features/unboxed-closures.md +++ b/src/doc/unstable-book/src/language-features/unboxed-closures.md @@ -2,7 +2,7 @@ The tracking issue for this feature is [#29625] -See Also: [`fn_traits`](library-features/fn-traits.html) +See Also: [`fn_traits`](../library-features/fn-traits.md) [#29625]: https://github.com/rust-lang/rust/issues/29625 diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md index edc039f896..343084b7db 100644 --- a/src/doc/unstable-book/src/language-features/unsized-locals.md +++ b/src/doc/unstable-book/src/language-features/unsized-locals.md @@ -117,9 +117,7 @@ fn main () { } ``` -One of the objectives of this feature is to allow `Box`, instead of `Box` in the future. See [#28796] for details. - -[#28796]: https://github.com/rust-lang/rust/issues/28796 +One of the objectives of this feature is to allow `Box`. ## Variable length arrays diff --git a/src/doc/unstable-book/src/library-features/borrow-state.md b/src/doc/unstable-book/src/library-features/borrow-state.md deleted file mode 100644 index 304b8dffe9..0000000000 --- a/src/doc/unstable-book/src/library-features/borrow-state.md +++ /dev/null @@ -1,7 +0,0 @@ -# `borrow_state` - -The tracking issue for this feature is: [#27733] - -[#27733]: https://github.com/rust-lang/rust/issues/27733 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md index 72a3f36c10..29a8aecee6 100644 --- a/src/doc/unstable-book/src/library-features/fn-traits.md +++ b/src/doc/unstable-book/src/library-features/fn-traits.md @@ -2,7 +2,7 @@ The tracking issue for this feature is [#29625] -See Also: [`unboxed_closures`](language-features/unboxed-closures.html) +See Also: [`unboxed_closures`](../language-features/unboxed-closures.md) [#29625]: https://github.com/rust-lang/rust/issues/29625 diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md deleted file mode 100644 index cb3386b715..0000000000 --- a/src/doc/unstable-book/src/library-features/fnbox.md +++ /dev/null @@ -1,32 +0,0 @@ -# `fnbox` - -The tracking issue for this feature is [#28796] - -[#28796]: https://github.com/rust-lang/rust/issues/28796 - ------------------------- - -This had been a temporary alternative to the following impls: - -```rust,ignore -impl FnOnce for Box where F: FnOnce + ?Sized {} -impl FnMut for Box where F: FnMut + ?Sized {} -impl Fn for Box where F: Fn + ?Sized {} -``` - -The impls are parallel to these (relatively old) impls: - -```rust,ignore -impl FnOnce for &mut F where F: FnMut + ?Sized {} -impl FnMut for &mut F where F: FnMut + ?Sized {} -impl Fn for &mut F where F: Fn + ?Sized {} -impl FnOnce for &F where F: Fn + ?Sized {} -impl FnMut for &F where F: Fn + ?Sized {} -impl Fn for &F where F: Fn + ?Sized {} -``` - -Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box` at that time. - -[unsized_locals]: language-features/unsized-locals.html - -`FnBox()` is an alternative approach to `Box` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box` working, the `fnbox` feature is going to be removed. diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md index 604b449f16..554c52c3c9 100644 --- a/src/doc/unstable-book/src/the-unstable-book.md +++ b/src/doc/unstable-book/src/the-unstable-book.md @@ -14,7 +14,7 @@ fn main() { The `box_syntax` feature [has a chapter][box] describing how to use it. -[box]: language-features/box-syntax.html +[box]: language-features/box-syntax.md Because this documentation relates to unstable features, we make no guarantees that what is contained here is accurate or up to date. It's developed on a diff --git a/src/etc/cpu-usage-over-time-plot.sh b/src/etc/cpu-usage-over-time-plot.sh new file mode 100755 index 0000000000..724a21c3fc --- /dev/null +++ b/src/etc/cpu-usage-over-time-plot.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# A small script to help visualizing CPU usage over time data collected on CI +# using `gnuplot`. +# +# This script is expected to be called with two arguments. The first is the full +# commit SHA of the build you're interested in, and the second is the name of +# the builder. For example: +# +# ./src/etc/cpu-usage-over-time-plot.sh e699ea096fcc2fc9ce8e8bcf884e11496a31cc9f i686-mingw-1 +# +# That will generate `$builder.png` in the current directory which you can open +# up to see a hopefully pretty graph. +# +# Improvements to this script are greatly appreciated! + +set -ex + +bucket=rust-lang-ci-evalazure +commit=$1 +builder=$2 + +curl -O https://$bucket.s3.amazonaws.com/rustc-builds/$commit/cpu-$builder.csv + +gnuplot <<-EOF +reset +set timefmt '%Y-%m-%dT%H:%M:%S' +set xdata time +set ylabel "CPU Usage %" +set xlabel "Time" +set datafile sep ',' +set term png size 3000,1000 +set output "$builder.png" +set grid + +f(x) = mean_y +fit f(x) 'cpu-$builder.csv' using 1:(100-\$2) via mean_y + +set label 1 gprintf("Average = %g%%", mean_y) center font ",18" +set label 1 at graph 0.50, 0.25 +set xtics rotate by 45 offset -2,-2.4 300 +set ytics 10 +set boxwidth 0.5 + +plot \\ + mean_y with lines linetype 1 linecolor rgb "#ff0000" title "average", \\ + "cpu-$builder.csv" using 1:(100-\$2) with points pointtype 7 pointsize 0.4 title "$builder", \\ + "" using 1:(100-\$2) smooth bezier linewidth 3 title "bezier" +EOF diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb index 424302d495..0eb99423df 100755 --- a/src/etc/rust-lldb +++ b/src/etc/rust-lldb @@ -31,7 +31,7 @@ category_definition="type summary add --no-value --python-function lldb_rust_for category_enable="type category enable Rust" # Call LLDB with the commands added to the argument list -exec "$lldb" --one-line-before-file="$script_import" \ - --one-line-before-file="$category_definition" \ - --one-line-before-file="$category_enable" \ +exec "$lldb" --one-line-before-file "$script_import" \ + --one-line-before-file "$category_definition" \ + --one-line-before-file "$category_enable" \ "$@" diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 41ff06d70f..755feb8496 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -15,7 +15,8 @@ extern "Rust" { // them from the `#[global_allocator]` attribute if there is one, or uses the // default implementations in libstd (`__rdl_alloc` etc in `src/libstd/alloc.rs`) // otherwise. - #[allocator] + #[cfg_attr(bootstrap, allocator)] + #[cfg_attr(not(bootstrap), rustc_allocator)] #[rustc_allocator_nounwind] fn __rust_alloc(size: usize, align: usize) -> *mut u8; #[rustc_allocator_nounwind] diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 207359ed69..9109a730cc 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -4,16 +4,6 @@ //! heap allocation in Rust. Boxes provide ownership for this allocation, and //! drop their contents when they go out of scope. //! -//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for -//! its allocation. It is valid to convert both ways between a [`Box`] and a -//! raw pointer allocated with the [`Global`] allocator, given that the -//! [`Layout`] used with the allocator is correct for the type. More precisely, -//! a `value: *mut T` that has been allocated with the [`Global`] allocator -//! with `Layout::for_value(&*value)` may be converted into a box using -//! `Box::::from_raw(value)`. Conversely, the memory backing a `value: *mut -//! T` obtained from `Box::::into_raw` may be deallocated using the -//! [`Global`] allocator with `Layout::for_value(&*value)`. -//! //! # Examples //! //! Move a value from the stack to the heap by creating a [`Box`]: @@ -61,6 +51,19 @@ //! for a `Cons`. By introducing a `Box`, which has a defined size, we know how //! big `Cons` needs to be. //! +//! # Memory layout +//! +//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for +//! its allocation. It is valid to convert both ways between a [`Box`] and a +//! raw pointer allocated with the [`Global`] allocator, given that the +//! [`Layout`] used with the allocator is correct for the type. More precisely, +//! a `value: *mut T` that has been allocated with the [`Global`] allocator +//! with `Layout::for_value(&*value)` may be converted into a box using +//! `Box::::from_raw(value)`. Conversely, the memory backing a `value: *mut +//! T` obtained from `Box::::into_raw` may be deallocated using the +//! [`Global`] allocator with `Layout::for_value(&*value)`. +//! +//! //! [dereferencing]: ../../std/ops/trait.Deref.html //! [`Box`]: struct.Box.html //! [`Global`]: ../alloc/struct.Global.html @@ -127,24 +130,38 @@ impl Box { /// /// After calling this function, the raw pointer is owned by the /// resulting `Box`. Specifically, the `Box` destructor will call - /// the destructor of `T` and free the allocated memory. Since the - /// way `Box` allocates and releases memory is unspecified, the - /// only valid pointer to pass to this function is the one taken - /// from another `Box` via the [`Box::into_raw`] function. + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety /// /// This function is unsafe because improper use may lead to /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// - /// [`Box::into_raw`]: struct.Box.html#method.into_raw - /// /// # Examples - /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw`]: /// ``` /// let x = Box::new(5); /// let ptr = Box::into_raw(x); /// let x = unsafe { Box::from_raw(ptr) }; /// ``` + /// Manually create a `Box` from scratch by using the global allocator: + /// ``` + /// use std::alloc::{alloc, Layout}; + /// + /// unsafe { + /// let ptr = alloc(Layout::new::()) as *mut i32; + /// *ptr = 5; + /// let x = Box::from_raw(ptr); + /// } + /// ``` + /// + /// [memory layout]: index.html#memory-layout + /// [`Layout`]: ../alloc/struct.Layout.html + /// [`Box::into_raw`]: struct.Box.html#method.into_raw #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { @@ -157,22 +174,40 @@ impl Box { /// /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `Box` with the [`Box::from_raw`] function. + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw`] function, allowing the `Box` destructor to perform + /// the cleanup. /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This /// is so that there is no conflict with a method on the inner type. /// - /// [`Box::from_raw`]: struct.Box.html#method.from_raw - /// /// # Examples - /// + /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] + /// for automatic cleanup: /// ``` - /// let x = Box::new(5); + /// let x = Box::new(String::from("Hello")); /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// use std::alloc::{dealloc, Layout}; + /// use std::ptr; + /// + /// let x = Box::new(String::from("Hello")); + /// let p = Box::into_raw(x); + /// unsafe { + /// ptr::drop_in_place(p); + /// dealloc(p as *mut u8, Layout::new::()); + /// } + /// ``` + /// + /// [memory layout]: index.html#memory-layout + /// [`Box::from_raw`]: struct.Box.html#method.from_raw #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Box) -> *mut T { @@ -184,7 +219,7 @@ impl Box { /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the `NonNull` pointer + /// easiest way to do so is to convert the `NonNull` pointer /// into a raw pointer and back into a `Box` with the [`Box::from_raw`] /// function. /// @@ -203,6 +238,10 @@ impl Box { /// fn main() { /// let x = Box::new(5); /// let ptr = Box::into_raw_non_null(x); + /// + /// // Clean up the memory by converting the NonNull pointer back + /// // into a Box and letting the Box be dropped. + /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; /// } /// ``` #[unstable(feature = "box_into_raw_non_null", issue = "47336")] @@ -214,15 +253,16 @@ impl Box { #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")] #[inline] #[doc(hidden)] - pub fn into_unique(mut b: Box) -> Unique { + pub fn into_unique(b: Box) -> Unique { + let mut unique = b.0; + mem::forget(b); // Box is kind-of a library type, but recognized as a "unique pointer" by // Stacked Borrows. This function here corresponds to "reborrowing to // a raw pointer", but there is no actual reborrow here -- so // without some care, the pointer we are returning here still carries - // the `Uniq` tag. We round-trip through a mutable reference to avoid that. - let unique = unsafe { b.0.as_mut() as *mut T }; - mem::forget(b); - unsafe { Unique::new_unchecked(unique) } + // the tag of `b`, with `Unique` permission. + // We round-trip through a mutable reference to avoid that. + unsafe { Unique::new_unchecked(unique.as_mut() as *mut T) } } /// Consumes and leaks the `Box`, returning a mutable reference, @@ -355,11 +395,10 @@ impl Clone for Box { #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box { fn clone(&self) -> Self { - let len = self.len(); - let buf = RawVec::with_capacity(len); + // this makes a copy of the data + let buf: Box<[u8]> = self.as_bytes().into(); unsafe { - ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len); - from_boxed_utf8_unchecked(buf.into_box()) + from_boxed_utf8_unchecked(buf) } } } @@ -506,9 +545,12 @@ impl From<&[T]> for Box<[T]> { /// println!("{:?}", boxed_slice); /// ``` fn from(slice: &[T]) -> Box<[T]> { - let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; - boxed.copy_from_slice(slice); - boxed + let len = slice.len(); + let buf = RawVec::with_capacity(len); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + buf.into_box() + } } } @@ -719,61 +761,6 @@ impl + ?Sized> Fn for Box { } } -/// `FnBox` is a version of the `FnOnce` intended for use with boxed -/// closure objects. The idea is that where one would normally store a -/// `Box` in a data structure, you should use -/// `Box`. The two traits behave essentially the same, except -/// that a `FnBox` closure can only be called if it is boxed. (Note -/// that `FnBox` may be deprecated in the future if `Box` -/// closures become directly usable.) -/// -/// # Examples -/// -/// Here is a snippet of code which creates a hashmap full of boxed -/// once closures and then removes them one by one, calling each -/// closure as it is removed. Note that the type of the closures -/// stored in the map is `Box i32>` and not `Box i32>`. -/// -/// ``` -/// #![feature(fnbox)] -/// -/// use std::boxed::FnBox; -/// use std::collections::HashMap; -/// -/// fn make_map() -> HashMap i32>> { -/// let mut map: HashMap i32>> = HashMap::new(); -/// map.insert(1, Box::new(|| 22)); -/// map.insert(2, Box::new(|| 44)); -/// map -/// } -/// -/// fn main() { -/// let mut map = make_map(); -/// for i in &[1, 2] { -/// let f = map.remove(&i).unwrap(); -/// assert_eq!(f(), i * 22); -/// } -/// } -/// ``` -#[rustc_paren_sugar] -#[unstable(feature = "fnbox", - reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] -pub trait FnBox: FnOnce { - /// Performs the call operation. - fn call_box(self: Box, args: A) -> Self::Output; -} - -#[unstable(feature = "fnbox", - reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] -impl FnBox for F - where F: FnOnce -{ - fn call_box(self: Box, args: A) -> F::Output { - self.call_once(args) - } -} - #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized> for Box {} diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 31e49d06a7..71faf67296 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2709,6 +2709,11 @@ impl fmt::Debug for VecDeque { #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] impl From> for VecDeque { + /// Turn a [`Vec`] into a [`VecDeque`]. + /// + /// This avoids reallocating where possible, but the conditions for that are + /// strict, and subject to change, and so shouldn't be relied upon unless the + /// `Vec` came from `From>` and hasn't been reallocated. fn from(mut other: Vec) -> Self { unsafe { let other_buf = other.as_mut_ptr(); @@ -2735,6 +2740,32 @@ impl From> for VecDeque { #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] impl From> for Vec { + /// Turn a [`VecDeque`] into a [`Vec`]. + /// + /// This never needs to re-allocate, but does need to do O(n) data movement if + /// the circular buffer doesn't happen to be at the beginning of the allocation. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// // This one is O(1). + /// let deque: VecDeque<_> = (1..5).collect(); + /// let ptr = deque.as_slices().0.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// + /// // This one needs data rearranging. + /// let mut deque: VecDeque<_> = (1..5).collect(); + /// deque.push_front(9); + /// deque.push_front(8); + /// let ptr = deque.as_slices().1.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// ``` fn from(other: VecDeque) -> Self { unsafe { let buf = other.buf.ptr(); diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d90036eaf4..5fc58c8ab5 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -79,7 +79,7 @@ #![feature(coerce_unsized)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] -#![feature(custom_attribute)] +#![cfg_attr(bootstrap, feature(custom_attribute))] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] @@ -112,7 +112,6 @@ #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)] #![feature(alloc_layout_extra)] #![feature(try_trait)] -#![feature(iter_nth_back)] // Allow testing this library @@ -142,7 +141,7 @@ mod boxed { pub use std::boxed::Box; } #[cfg(test)] -mod boxed_test; +mod tests; pub mod collections; #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] pub mod sync; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index d1fc5ac3b3..0454a56443 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -685,12 +685,14 @@ impl RawVec { impl RawVec { /// Converts the entire buffer into `Box<[T]>`. /// - /// While it is not *strictly* Undefined Behavior to call - /// this procedure while some of the RawVec is uninitialized, - /// it certainly makes it trivial to trigger it. - /// /// Note that this will correctly reconstitute any `cap` changes /// that may have been performed. (see description of type for details) + /// + /// # Undefined Behavior + /// + /// All elements of `RawVec` must be initialized. Notice that + /// the rules around uninitialized boxed values are not finalized yet, + /// but until they are, it is advisable to avoid them. pub unsafe fn into_box(self) -> Box<[T]> { // NOTE: not calling `cap()` here, actually using the real `cap` field! let slice = slice::from_raw_parts_mut(self.ptr(), self.cap); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0dffb19476..ee78839f7f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -239,7 +239,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::marker::{self, Unpin, Unsize, PhantomData}; -use core::mem::{self, align_of_val, forget, size_of_val}; +use core::mem::{self, align_of, align_of_val, forget, size_of_val}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -375,9 +375,9 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let x = Rc::new(10); + /// let x = Rc::new("hello".to_owned()); /// let x_ptr = Rc::into_raw(x); - /// assert_eq!(unsafe { *x_ptr }, 10); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { @@ -401,13 +401,13 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let x = Rc::new(10); + /// let x = Rc::new("hello".to_owned()); /// let x_ptr = Rc::into_raw(x); /// /// unsafe { /// // Convert back to an `Rc` to prevent leak. /// let x = Rc::from_raw(x_ptr); - /// assert_eq!(*x, 10); + /// assert_eq!(&*x, "hello"); /// /// // Further calls to `Rc::from_raw(x_ptr)` would be memory unsafe. /// } @@ -416,11 +416,7 @@ impl Rc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // Align the unsized value to the end of the RcBox. - // Because it is ?Sized, it will always be the last field in memory. - let align = align_of_val(&*ptr); - let layout = Layout::new::>(); - let offset = (layout.size() + layout.padding_needed_for(align)) as isize; + let offset = data_offset(ptr); // Reverse the offset to find the original RcBox. let fake_ptr = ptr as *mut RcBox; @@ -441,10 +437,10 @@ impl Rc { /// /// use std::rc::Rc; /// - /// let x = Rc::new(10); + /// let x = Rc::new("hello".to_owned()); /// let ptr = Rc::into_raw_non_null(x); - /// let deref = unsafe { *ptr.as_ref() }; - /// assert_eq!(deref, 10); + /// let deref = unsafe { ptr.as_ref() }; + /// assert_eq!(deref, "hello"); /// ``` #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] #[inline] @@ -584,15 +580,18 @@ impl Rc { impl Rc { /// Makes a mutable reference into the given `Rc`. /// - /// If there are other `Rc` or [`Weak`][weak] pointers to the same value, - /// then `make_mut` will invoke [`clone`][clone] on the inner value to - /// ensure unique ownership. This is also referred to as clone-on-write. + /// If there are other `Rc` pointers to the same value, then `make_mut` will + /// [`clone`] the inner value to ensure unique ownership. This is also + /// referred to as clone-on-write. /// - /// See also [`get_mut`][get_mut], which will fail rather than cloning. + /// If there are no other `Rc` pointers to this value, then [`Weak`] + /// pointers to this value will be dissassociated. /// - /// [weak]: struct.Weak.html - /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone - /// [get_mut]: struct.Rc.html#method.get_mut + /// See also [`get_mut`], which will fail rather than cloning. + /// + /// [`Weak`]: struct.Weak.html + /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone + /// [`get_mut`]: struct.Rc.html#method.get_mut /// /// # Examples /// @@ -611,6 +610,23 @@ impl Rc { /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` + /// + /// [`Weak`] pointers will be dissassociated: + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut data = Rc::new(75); + /// let weak = Rc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Rc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { @@ -1262,6 +1278,143 @@ impl Weak { ptr: NonNull::new(usize::MAX as *mut RcBox).expect("MAX is not 0"), } } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// It is up to the caller to ensure that the object is still alive when accessing it through + /// the pointer. + /// + /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// use std::ptr; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak))); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) }); + /// + /// drop(strong); + /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) }); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_raw(this: &Self) -> *const T { + match this.inner() { + None => ptr::null(), + Some(inner) => { + let offset = data_offset_sized::(); + let ptr = inner as *const RcBox; + // Note: while the pointer we create may already point to dropped value, the + // allocation still lives (it must hold the weak point as long as we are alive). + // Therefore, the offset is OK to do, it won't get out of the allocation. + let ptr = unsafe { (ptr as *const u8).offset(offset) }; + ptr as *const T + } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, preserving the original weak count. It + /// can be turned back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_raw`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// let raw = Weak::into_raw(weak); + /// + /// assert_eq!(1, Rc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Rc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: struct.Weak.html#method.from_raw + /// [`as_raw`]: struct.Weak.html#method.as_raw + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn into_raw(this: Self) -> *const T { + let result = Self::as_raw(&this); + mem::forget(this); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is + /// returned. + /// + /// # Safety + /// + /// The pointer must represent one valid weak count. In other words, it must point to `T` which + /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached + /// 0. It is allowed for the strong count to be 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// + /// let raw_1 = Weak::into_raw(Rc::downgrade(&strong)); + /// let raw_2 = Weak::into_raw(Rc::downgrade(&strong)); + /// + /// assert_eq!(2, Rc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap()); + /// assert_eq!(1, Rc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none()); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + /// [`into_raw`]: struct.Weak.html#method.into_raw + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`Rc`]: struct.Rc.html + /// [`Weak`]: struct.Weak.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + if ptr.is_null() { + Self::new() + } else { + // See Rc::from_raw for details + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut RcBox; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { + ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"), + } + } + } } pub(crate) fn is_dangling(ptr: NonNull) -> bool { @@ -1362,18 +1515,18 @@ impl Weak { /// /// ``` /// #![feature(weak_ptr_eq)] - /// use std::rc::{Rc, Weak}; + /// use std::rc::Rc; /// /// let first_rc = Rc::new(5); /// let first = Rc::downgrade(&first_rc); /// let second = Rc::downgrade(&first_rc); /// - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Rc::new(5); /// let third = Rc::downgrade(&third_rc); /// - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` /// /// Comparing `Weak::new`. @@ -1384,16 +1537,16 @@ impl Weak { /// /// let first = Weak::new(); /// let second = Weak::new(); - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Rc::new(()); /// let third = Rc::downgrade(&third_rc); - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` #[inline] #[unstable(feature = "weak_ptr_eq", issue = "55981")] - pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() == other.ptr.as_ptr() + pub fn ptr_eq(&self, other: &Self) -> bool { + self.ptr.as_ptr() == other.ptr.as_ptr() } } @@ -2007,3 +2160,20 @@ impl AsRef for Rc { #[stable(feature = "pin", since = "1.33.0")] impl Unpin for Rc { } + +unsafe fn data_offset(ptr: *const T) -> isize { + // Align the unsized value to the end of the RcBox. + // Because it is ?Sized, it will always be the last field in memory. + let align = align_of_val(&*ptr); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} + +/// Computes the offset of the data field within ArcInner. +/// +/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. +fn data_offset_sized() -> isize { + let align = align_of::(); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 6eac848740..f7b0a5e703 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -123,12 +123,12 @@ pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut}; //////////////////////////////////////////////////////////////////////////////// // HACK(japaric) needed for the implementation of `vec!` macro during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::into_vec; // HACK(japaric) needed for the implementation of `Vec::clone` during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::to_vec; @@ -137,17 +137,16 @@ pub use hack::to_vec; // `core::slice::SliceExt` - we need to supply these functions for the // `test_permutations` test mod hack { - use core::mem; - use crate::boxed::Box; use crate::vec::Vec; #[cfg(test)] use crate::string::ToString; - pub fn into_vec(mut b: Box<[T]>) -> Vec { + pub fn into_vec(b: Box<[T]>) -> Vec { unsafe { - let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len()); - mem::forget(b); + let len = b.len(); + let b = Box::into_raw(b); + let xs = Vec::from_raw_parts(b as *mut T, len, len); xs } } @@ -376,7 +375,7 @@ impl [T] { pub fn to_vec(&self) -> Vec where T: Clone { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::to_vec(self) } @@ -397,7 +396,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn into_vec(self: Box) -> Vec { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::into_vec(self) } @@ -582,7 +581,9 @@ pub trait SliceConcatExt { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] - fn connect(&self, sep: &T) -> Self::Output; + fn connect(&self, sep: &T) -> Self::Output { + self.join(sep) + } } #[unstable(feature = "slice_concat_ext", @@ -616,10 +617,6 @@ impl> SliceConcatExt for [V] { } result } - - fn connect(&self, sep: &T) -> Vec { - self.join(sep) - } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index f66ff894ae..40104554fe 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -86,10 +86,6 @@ impl> SliceConcatExt for [S] { String::from_utf8_unchecked( join_generic_copy(self, sep.as_bytes()) ) } } - - fn connect(&self, sep: &str) -> String { - self.join(sep) - } } macro_rules! spezialize_for_lengths { @@ -431,6 +427,13 @@ impl str { /// /// assert_eq!(new_year, new_year.to_uppercase()); /// ``` + /// + /// One character can become multiple: + /// ``` + /// let s = "tschüß"; + /// + /// assert_eq!("TSCHÜSS", s.to_uppercase()); + /// ``` #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_uppercase(&self) -> String { let mut s = String::with_capacity(self.len()); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 90c7859b3d..6c23b3179e 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -13,7 +13,7 @@ use core::borrow; use core::fmt; use core::cmp::{self, Ordering}; use core::intrinsics::abort; -use core::mem::{self, align_of_val, size_of_val}; +use core::mem::{self, align_of, align_of_val, size_of_val}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -356,9 +356,9 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let x = Arc::new(10); + /// let x = Arc::new("hello".to_owned()); /// let x_ptr = Arc::into_raw(x); - /// assert_eq!(unsafe { *x_ptr }, 10); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { @@ -382,13 +382,13 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let x = Arc::new(10); + /// let x = Arc::new("hello".to_owned()); /// let x_ptr = Arc::into_raw(x); /// /// unsafe { /// // Convert back to an `Arc` to prevent leak. /// let x = Arc::from_raw(x_ptr); - /// assert_eq!(*x, 10); + /// assert_eq!(&*x, "hello"); /// /// // Further calls to `Arc::from_raw(x_ptr)` would be memory unsafe. /// } @@ -397,11 +397,7 @@ impl Arc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // Align the unsized value to the end of the ArcInner. - // Because it is ?Sized, it will always be the last field in memory. - let align = align_of_val(&*ptr); - let layout = Layout::new::>(); - let offset = (layout.size() + layout.padding_needed_for(align)) as isize; + let offset = data_offset(ptr); // Reverse the offset to find the original ArcInner. let fake_ptr = ptr as *mut ArcInner; @@ -422,10 +418,10 @@ impl Arc { /// /// use std::sync::Arc; /// - /// let x = Arc::new(10); + /// let x = Arc::new("hello".to_owned()); /// let ptr = Arc::into_raw_non_null(x); - /// let deref = unsafe { *ptr.as_ref() }; - /// assert_eq!(deref, 10); + /// let deref = unsafe { ptr.as_ref() }; + /// assert_eq!(deref, "hello"); /// ``` #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] #[inline] @@ -1071,6 +1067,144 @@ impl Weak { ptr: NonNull::new(usize::MAX as *mut ArcInner).expect("MAX is not 0"), } } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// It is up to the caller to ensure that the object is still alive when accessing it through + /// the pointer. + /// + /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// use std::ptr; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak))); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) }); + /// + /// drop(strong); + /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) }); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_raw(this: &Self) -> *const T { + match this.inner() { + None => ptr::null(), + Some(inner) => { + let offset = data_offset_sized::(); + let ptr = inner as *const ArcInner; + // Note: while the pointer we create may already point to dropped value, the + // allocation still lives (it must hold the weak point as long as we are alive). + // Therefore, the offset is OK to do, it won't get out of the allocation. + let ptr = unsafe { (ptr as *const u8).offset(offset) }; + ptr as *const T + } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, preserving the original weak count. It + /// can be turned back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_raw`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// let raw = Weak::into_raw(weak); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: struct.Weak.html#method.from_raw + /// [`as_raw`]: struct.Weak.html#method.as_raw + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn into_raw(this: Self) -> *const T { + let result = Self::as_raw(&this); + mem::forget(this); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into + /// `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is + /// returned. + /// + /// # Safety + /// + /// The pointer must represent one valid weak count. In other words, it must point to `T` which + /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached + /// 0. It is allowed for the strong count to be 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// + /// let raw_1 = Weak::into_raw(Arc::downgrade(&strong)); + /// let raw_2 = Weak::into_raw(Arc::downgrade(&strong)); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none()); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + /// [`into_raw`]: struct.Weak.html#method.into_raw + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`Weak`]: struct.Weak.html + /// [`Arc`]: struct.Arc.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + if ptr.is_null() { + Self::new() + } else { + // See Arc::from_raw for details + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut ArcInner; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { + ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"), + } + } + } } impl Weak { @@ -1215,18 +1349,18 @@ impl Weak { /// /// ``` /// #![feature(weak_ptr_eq)] - /// use std::sync::{Arc, Weak}; + /// use std::sync::Arc; /// /// let first_rc = Arc::new(5); /// let first = Arc::downgrade(&first_rc); /// let second = Arc::downgrade(&first_rc); /// - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Arc::new(5); /// let third = Arc::downgrade(&third_rc); /// - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` /// /// Comparing `Weak::new`. @@ -1237,16 +1371,16 @@ impl Weak { /// /// let first = Weak::new(); /// let second = Weak::new(); - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Arc::new(()); /// let third = Arc::downgrade(&third_rc); - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` #[inline] #[unstable(feature = "weak_ptr_eq", issue = "55981")] - pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() == other.ptr.as_ptr() + pub fn ptr_eq(&self, other: &Self) -> bool { + self.ptr.as_ptr() == other.ptr.as_ptr() } } @@ -2150,3 +2284,21 @@ impl AsRef for Arc { #[stable(feature = "pin", since = "1.33.0")] impl Unpin for Arc { } + +/// Computes the offset of the data field within ArcInner. +unsafe fn data_offset(ptr: *const T) -> isize { + // Align the unsized value to the end of the ArcInner. + // Because it is ?Sized, it will always be the last field in memory. + let align = align_of_val(&*ptr); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} + +/// Computes the offset of the data field within ArcInner. +/// +/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. +fn data_offset_sized() -> isize { + let align = align_of::(); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/tests.rs similarity index 100% rename from src/liballoc/boxed_test.rs rename to src/liballoc/tests.rs diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 545332bcd6..5ddac673c9 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -1,5 +1,3 @@ -#![cfg(not(miri))] - use std::borrow::Cow; use std::mem::size_of; use std::{usize, isize}; @@ -763,6 +761,7 @@ fn from_into_inner() { it.next().unwrap(); let vec = it.collect::>(); assert_eq!(vec, [2, 3]); + #[cfg(not(miri))] // Miri does not support comparing dangling pointers assert!(ptr != vec.as_ptr()); } @@ -971,6 +970,7 @@ fn test_reserve_exact() { } #[test] +#[cfg(not(miri))] // Miri does not support signalling OOM fn test_try_reserve() { // These are the interesting cases: @@ -1073,6 +1073,7 @@ fn test_try_reserve() { } #[test] +#[cfg(not(miri))] // Miri does not support signalling OOM fn test_try_reserve_exact() { // This is exactly the same as test_try_reserve with the method changed. @@ -1151,3 +1152,24 @@ fn test_try_reserve_exact() { } } + +#[test] +fn test_stable_push_pop() { + // Test that, if we reserved enough space, adding and removing elements does not + // invalidate references into the vector (such as `v0`). This test also + // runs in Miri, which would detect such problems. + let mut v = Vec::with_capacity(10); + v.push(13); + + // laundering the lifetime -- we take care that `v` does not reallocate, so that's okay. + let v0 = unsafe { &*(&v[0] as *const _) }; + + // Now do a bunch of things and occasionally use `v0` again to assert it is still valid. + v.push(1); + v.push(2); + v.insert(1, 1); + assert_eq!(*v0, 13); + v.remove(1); + v.pop().unwrap(); + assert_eq!(*v0, 13); +} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 073d3ab593..92fe0834dd 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -735,6 +735,75 @@ impl Vec { self } + /// Returns a raw pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// # Examples + /// + /// ``` + /// let x = vec![1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(*x_ptr.add(i), 1 << i); + /// } + /// } + /// ``` + /// + /// [`as_mut_ptr`]: #method.as_mut_ptr + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + // We shadow the slice method of the same name to avoid going through + // `deref`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { assume(!ptr.is_null()); } + ptr + } + + /// Returns an unsafe mutable pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec = Vec::with_capacity(size); + /// let x_ptr = x.as_mut_ptr(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// *x_ptr.add(i) = i as i32; + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0,1,2,3]); + /// ``` + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + // We shadow the slice method of the same name to avoid going through + // `deref_mut`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { assume(!ptr.is_null()); } + ptr + } + /// Forces the length of the vector to `new_len`. /// /// This is a low-level operation that maintains none of the normal @@ -1094,7 +1163,7 @@ impl Vec { let count = (*other).len(); self.reserve(count); let len = self.len(); - ptr::copy_nonoverlapping(other as *const T, self.get_unchecked_mut(len), count); + ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count); self.len += count; } @@ -1706,9 +1775,7 @@ impl ops::Deref for Vec { fn deref(&self) -> &[T] { unsafe { - let p = self.buf.ptr(); - assume(!p.is_null()); - slice::from_raw_parts(p, self.len) + slice::from_raw_parts(self.as_ptr(), self.len) } } } @@ -1717,9 +1784,7 @@ impl ops::Deref for Vec { impl ops::DerefMut for Vec { fn deref_mut(&mut self) -> &mut [T] { unsafe { - let ptr = self.buf.ptr(); - assume(!ptr.is_null()); - slice::from_raw_parts_mut(ptr, self.len) + slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } } } @@ -1754,7 +1819,6 @@ impl IntoIterator for Vec { fn into_iter(mut self) -> IntoIter { unsafe { let begin = self.as_mut_ptr(); - assume(!begin.is_null()); let end = if mem::size_of::() == 0 { arith_offset(begin as *const i8, self.len() as isize) as *const T } else { @@ -1954,16 +2018,14 @@ impl Vec { /// with the given `replace_with` iterator and yields the removed items. /// `replace_with` does not need to be the same length as `range`. /// - /// Note 1: The element range is removed even if the iterator is not - /// consumed until the end. + /// The element range is removed even if the iterator is not consumed until the end. /// - /// Note 2: It is unspecified how many elements are removed from the vector, + /// It is unspecified how many elements are removed from the vector /// if the `Splice` value is leaked. /// - /// Note 3: The input iterator `replace_with` is only consumed - /// when the `Splice` value is dropped. + /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. /// - /// Note 4: This is optimal if: + /// This is optimal if: /// /// * The tail (elements in the vector after `range`) is empty, /// * or `replace_with` yields fewer elements than `range`’s length diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index ce5e5f23a9..3d16e335cd 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -13,6 +13,7 @@ #![deny(rust_2018_idioms)] #![deny(internal)] +#![deny(unused_lifetimes)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] @@ -113,8 +114,8 @@ impl Default for TypedArena { TypedArena { // We set both `ptr` and `end` to 0 so that the first call to // alloc() will trigger a grow(). - ptr: Cell::new(0 as *mut T), - end: Cell::new(0 as *mut T), + ptr: Cell::new(ptr::null_mut()), + end: Cell::new(ptr::null_mut()), chunks: RefCell::new(vec![]), _own: PhantomData, } @@ -369,8 +370,8 @@ impl Default for DroplessArena { #[inline] fn default() -> DroplessArena { DroplessArena { - ptr: Cell::new(0 as *mut u8), - end: Cell::new(0 as *mut u8), + ptr: Cell::new(ptr::null_mut()), + end: Cell::new(ptr::null_mut()), chunks: Default::default(), } } @@ -486,9 +487,31 @@ impl DroplessArena { } } + #[inline] + unsafe fn write_from_iter>( + &self, + mut iter: I, + len: usize, + mem: *mut T, + ) -> &mut [T] { + let mut i = 0; + // Use a manual loop since LLVM manages to optimize it better for + // slice iterators + loop { + let value = iter.next(); + if i >= len || value.is_none() { + // We only return as many items as the iterator gave us, even + // though it was supposed to give us `len` + return slice::from_raw_parts_mut(mem, i); + } + ptr::write(mem.offset(i as isize), value.unwrap()); + i += 1; + } + } + #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { - let mut iter = iter.into_iter(); + let iter = iter.into_iter(); assert!(mem::size_of::() != 0); assert!(!mem::needs_drop::()); @@ -505,10 +528,7 @@ impl DroplessArena { let size = len.checked_mul(mem::size_of::()).unwrap(); let mem = self.alloc_raw(size, mem::align_of::()) as *mut _ as *mut T; unsafe { - for i in 0..len { - ptr::write(mem.offset(i as isize), iter.next().unwrap()) - } - slice::from_raw_parts_mut(mem, len) + self.write_from_iter(iter, len, mem) } } (_, _) => { @@ -597,218 +617,4 @@ impl SyncDroplessArena { } #[cfg(test)] -mod tests { - extern crate test; - use test::Bencher; - use super::TypedArena; - use std::cell::Cell; - - #[allow(dead_code)] - #[derive(Debug, Eq, PartialEq)] - struct Point { - x: i32, - y: i32, - z: i32, - } - - #[test] - pub fn test_unused() { - let arena: TypedArena = TypedArena::default(); - assert!(arena.chunks.borrow().is_empty()); - } - - #[test] - fn test_arena_alloc_nested() { - struct Inner { - value: u8, - } - struct Outer<'a> { - inner: &'a Inner, - } - enum EI<'e> { - I(Inner), - O(Outer<'e>), - } - - struct Wrap<'a>(TypedArena>); - - impl<'a> Wrap<'a> { - fn alloc_inner Inner>(&self, f: F) -> &Inner { - let r: &EI<'_> = self.0.alloc(EI::I(f())); - if let &EI::I(ref i) = r { - i - } else { - panic!("mismatch"); - } - } - fn alloc_outer Outer<'a>>(&self, f: F) -> &Outer<'_> { - let r: &EI<'_> = self.0.alloc(EI::O(f())); - if let &EI::O(ref o) = r { - o - } else { - panic!("mismatch"); - } - } - } - - let arena = Wrap(TypedArena::default()); - - let result = arena.alloc_outer(|| Outer { - inner: arena.alloc_inner(|| Inner { value: 10 }), - }); - - assert_eq!(result.inner.value, 10); - } - - #[test] - pub fn test_copy() { - let arena = TypedArena::default(); - for _ in 0..100000 { - arena.alloc(Point { x: 1, y: 2, z: 3 }); - } - } - - #[bench] - pub fn bench_copy(b: &mut Bencher) { - let arena = TypedArena::default(); - b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 })) - } - - #[bench] - pub fn bench_copy_nonarena(b: &mut Bencher) { - b.iter(|| { - let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 }); - }) - } - - #[allow(dead_code)] - struct Noncopy { - string: String, - array: Vec, - } - - #[test] - pub fn test_noncopy() { - let arena = TypedArena::default(); - for _ in 0..100000 { - arena.alloc(Noncopy { - string: "hello world".to_string(), - array: vec![1, 2, 3, 4, 5], - }); - } - } - - #[test] - pub fn test_typed_arena_zero_sized() { - let arena = TypedArena::default(); - for _ in 0..100000 { - arena.alloc(()); - } - } - - #[test] - pub fn test_typed_arena_clear() { - let mut arena = TypedArena::default(); - for _ in 0..10 { - arena.clear(); - for _ in 0..10000 { - arena.alloc(Point { x: 1, y: 2, z: 3 }); - } - } - } - - #[bench] - pub fn bench_typed_arena_clear(b: &mut Bencher) { - let mut arena = TypedArena::default(); - b.iter(|| { - arena.alloc(Point { x: 1, y: 2, z: 3 }); - arena.clear(); - }) - } - - // Drop tests - - struct DropCounter<'a> { - count: &'a Cell, - } - - impl Drop for DropCounter<'_> { - fn drop(&mut self) { - self.count.set(self.count.get() + 1); - } - } - - #[test] - fn test_typed_arena_drop_count() { - let counter = Cell::new(0); - { - let arena: TypedArena> = TypedArena::default(); - for _ in 0..100 { - // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(DropCounter { count: &counter }); - } - }; - assert_eq!(counter.get(), 100); - } - - #[test] - fn test_typed_arena_drop_on_clear() { - let counter = Cell::new(0); - let mut arena: TypedArena> = TypedArena::default(); - for i in 0..10 { - for _ in 0..100 { - // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(DropCounter { count: &counter }); - } - arena.clear(); - assert_eq!(counter.get(), i * 100 + 100); - } - } - - thread_local! { - static DROP_COUNTER: Cell = Cell::new(0) - } - - struct SmallDroppable; - - impl Drop for SmallDroppable { - fn drop(&mut self) { - DROP_COUNTER.with(|c| c.set(c.get() + 1)); - } - } - - #[test] - fn test_typed_arena_drop_small_count() { - DROP_COUNTER.with(|c| c.set(0)); - { - let arena: TypedArena = TypedArena::default(); - for _ in 0..100 { - // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(SmallDroppable); - } - // dropping - }; - assert_eq!(DROP_COUNTER.with(|c| c.get()), 100); - } - - #[bench] - pub fn bench_noncopy(b: &mut Bencher) { - let arena = TypedArena::default(); - b.iter(|| { - arena.alloc(Noncopy { - string: "hello world".to_string(), - array: vec![1, 2, 3, 4, 5], - }) - }) - } - - #[bench] - pub fn bench_noncopy_nonarena(b: &mut Bencher) { - b.iter(|| { - let _: Box<_> = Box::new(Noncopy { - string: "hello world".to_string(), - array: vec![1, 2, 3, 4, 5], - }); - }) - } -} +mod tests; diff --git a/src/libarena/tests.rs b/src/libarena/tests.rs new file mode 100644 index 0000000000..fa4189409d --- /dev/null +++ b/src/libarena/tests.rs @@ -0,0 +1,213 @@ +extern crate test; +use test::Bencher; +use super::TypedArena; +use std::cell::Cell; + +#[allow(dead_code)] +#[derive(Debug, Eq, PartialEq)] +struct Point { + x: i32, + y: i32, + z: i32, +} + +#[test] +pub fn test_unused() { + let arena: TypedArena = TypedArena::default(); + assert!(arena.chunks.borrow().is_empty()); +} + +#[test] +fn test_arena_alloc_nested() { + struct Inner { + value: u8, + } + struct Outer<'a> { + inner: &'a Inner, + } + enum EI<'e> { + I(Inner), + O(Outer<'e>), + } + + struct Wrap<'a>(TypedArena>); + + impl<'a> Wrap<'a> { + fn alloc_inner Inner>(&self, f: F) -> &Inner { + let r: &EI<'_> = self.0.alloc(EI::I(f())); + if let &EI::I(ref i) = r { + i + } else { + panic!("mismatch"); + } + } + fn alloc_outer Outer<'a>>(&self, f: F) -> &Outer<'_> { + let r: &EI<'_> = self.0.alloc(EI::O(f())); + if let &EI::O(ref o) = r { + o + } else { + panic!("mismatch"); + } + } + } + + let arena = Wrap(TypedArena::default()); + + let result = arena.alloc_outer(|| Outer { + inner: arena.alloc_inner(|| Inner { value: 10 }), + }); + + assert_eq!(result.inner.value, 10); +} + +#[test] +pub fn test_copy() { + let arena = TypedArena::default(); + for _ in 0..100000 { + arena.alloc(Point { x: 1, y: 2, z: 3 }); + } +} + +#[bench] +pub fn bench_copy(b: &mut Bencher) { + let arena = TypedArena::default(); + b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 })) +} + +#[bench] +pub fn bench_copy_nonarena(b: &mut Bencher) { + b.iter(|| { + let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 }); + }) +} + +#[allow(dead_code)] +struct Noncopy { + string: String, + array: Vec, +} + +#[test] +pub fn test_noncopy() { + let arena = TypedArena::default(); + for _ in 0..100000 { + arena.alloc(Noncopy { + string: "hello world".to_string(), + array: vec![1, 2, 3, 4, 5], + }); + } +} + +#[test] +pub fn test_typed_arena_zero_sized() { + let arena = TypedArena::default(); + for _ in 0..100000 { + arena.alloc(()); + } +} + +#[test] +pub fn test_typed_arena_clear() { + let mut arena = TypedArena::default(); + for _ in 0..10 { + arena.clear(); + for _ in 0..10000 { + arena.alloc(Point { x: 1, y: 2, z: 3 }); + } + } +} + +#[bench] +pub fn bench_typed_arena_clear(b: &mut Bencher) { + let mut arena = TypedArena::default(); + b.iter(|| { + arena.alloc(Point { x: 1, y: 2, z: 3 }); + arena.clear(); + }) +} + +// Drop tests + +struct DropCounter<'a> { + count: &'a Cell, +} + +impl Drop for DropCounter<'_> { + fn drop(&mut self) { + self.count.set(self.count.get() + 1); + } +} + +#[test] +fn test_typed_arena_drop_count() { + let counter = Cell::new(0); + { + let arena: TypedArena> = TypedArena::default(); + for _ in 0..100 { + // Allocate something with drop glue to make sure it doesn't leak. + arena.alloc(DropCounter { count: &counter }); + } + }; + assert_eq!(counter.get(), 100); +} + +#[test] +fn test_typed_arena_drop_on_clear() { + let counter = Cell::new(0); + let mut arena: TypedArena> = TypedArena::default(); + for i in 0..10 { + for _ in 0..100 { + // Allocate something with drop glue to make sure it doesn't leak. + arena.alloc(DropCounter { count: &counter }); + } + arena.clear(); + assert_eq!(counter.get(), i * 100 + 100); + } +} + +thread_local! { + static DROP_COUNTER: Cell = Cell::new(0) +} + +struct SmallDroppable; + +impl Drop for SmallDroppable { + fn drop(&mut self) { + DROP_COUNTER.with(|c| c.set(c.get() + 1)); + } +} + +#[test] +fn test_typed_arena_drop_small_count() { + DROP_COUNTER.with(|c| c.set(0)); + { + let arena: TypedArena = TypedArena::default(); + for _ in 0..100 { + // Allocate something with drop glue to make sure it doesn't leak. + arena.alloc(SmallDroppable); + } + // dropping + }; + assert_eq!(DROP_COUNTER.with(|c| c.get()), 100); +} + +#[bench] +pub fn bench_noncopy(b: &mut Bencher) { + let arena = TypedArena::default(); + b.iter(|| { + arena.alloc(Noncopy { + string: "hello world".to_string(), + array: vec![1, 2, 3, 4, 5], + }) + }) +} + +#[bench] +pub fn bench_noncopy_nonarena(b: &mut Bencher) { + b.iter(|| { + let _: Box<_> = Box::new(Noncopy { + string: "hello world".to_string(), + array: vec![1, 2, 3, 4, 5], + }); + }) +} diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs index 10b6cc61d9..a337c46713 100644 --- a/src/libcore/benches/ascii.rs +++ b/src/libcore/benches/ascii.rs @@ -191,7 +191,7 @@ benches! { fn case11_mask_mult_bool_match_range(bytes: &mut [u8]) { fn is_ascii_lowercase(b: u8) -> bool { match b { - b'a'...b'z' => true, + b'a'..=b'z' => true, _ => false } } @@ -203,7 +203,7 @@ benches! { fn case12_mask_shifted_bool_match_range(bytes: &mut [u8]) { fn is_ascii_lowercase(b: u8) -> bool { match b { - b'a'...b'z' => true, + b'a'..=b'z' => true, _ => false } } @@ -215,7 +215,7 @@ benches! { fn case13_subtract_shifted_bool_match_range(bytes: &mut [u8]) { fn is_ascii_lowercase(b: u8) -> bool { match b { - b'a'...b'z' => true, + b'a'..=b'z' => true, _ => false } } @@ -227,7 +227,7 @@ benches! { fn case14_subtract_multiplied_bool_match_range(bytes: &mut [u8]) { fn is_ascii_lowercase(b: u8) -> bool { match b { - b'a'...b'z' => true, + b'a'..=b'z' => true, _ => false } } diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index fcfd80d926..beafddc5a1 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -11,7 +11,7 @@ //! mutate it. //! //! Shareable mutable containers exist to permit mutability in a controlled manner, even in the -//! presence of aliasing. Both `Cell` and `RefCell` allows to do this in a single threaded +//! presence of aliasing. Both `Cell` and `RefCell` allow doing this in a single-threaded //! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement //! `Sync`). If you need to do aliasing and mutation between multiple threads it is possible to //! use [`Mutex`](../../std/sync/struct.Mutex.html), @@ -67,16 +67,26 @@ //! mutability: //! //! ``` +//! use std::cell::{RefCell, RefMut}; //! use std::collections::HashMap; -//! use std::cell::RefCell; //! use std::rc::Rc; //! //! fn main() { //! let shared_map: Rc> = Rc::new(RefCell::new(HashMap::new())); -//! shared_map.borrow_mut().insert("africa", 92388); -//! shared_map.borrow_mut().insert("kyoto", 11837); -//! shared_map.borrow_mut().insert("piccadilly", 11826); -//! shared_map.borrow_mut().insert("marbles", 38); +//! // Create a new block to limit the scope of the dynamic borrow +//! { +//! let mut map: RefMut<_> = shared_map.borrow_mut(); +//! map.insert("africa", 92388); +//! map.insert("kyoto", 11837); +//! map.insert("piccadilly", 11826); +//! map.insert("marbles", 38); +//! } +//! +//! // Note that if we had not let the previous borrow of the cache fall out +//! // of scope then the subsequent borrow would cause a dynamic thread panic. +//! // This is the major hazard of using `RefCell`. +//! let total: i32 = shared_map.borrow().values().sum(); +//! println!("{}", total); //! } //! ``` //! @@ -102,27 +112,15 @@ //! //! impl Graph { //! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> { -//! // Create a new scope to contain the lifetime of the -//! // dynamic borrow -//! { -//! // Take a reference to the inside of cache cell -//! let mut cache = self.span_tree_cache.borrow_mut(); -//! if cache.is_some() { -//! return cache.as_ref().unwrap().clone(); -//! } -//! -//! let span_tree = self.calc_span_tree(); -//! *cache = Some(span_tree); -//! } +//! self.span_tree_cache.borrow_mut() +//! .get_or_insert_with(|| self.calc_span_tree()) +//! .clone() +//! } //! -//! // Recursive call to return the just-cached value. -//! // Note that if we had not let the previous borrow -//! // of the cache fall out of scope then the subsequent -//! // recursive borrow would cause a dynamic thread panic. -//! // This is the major hazard of using `RefCell`. -//! self.minimum_spanning_tree() +//! fn calc_span_tree(&self) -> Vec<(i32, i32)> { +//! // Expensive computation goes here +//! vec![] //! } -//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] } //! } //! ``` //! @@ -496,7 +494,6 @@ impl Cell { /// # Examples /// /// ``` - /// #![feature(as_cell)] /// use std::cell::Cell; /// /// let slice: &mut [i32] = &mut [1, 2, 3]; @@ -506,7 +503,7 @@ impl Cell { /// assert_eq!(slice_cell.len(), 3); /// ``` #[inline] - #[unstable(feature = "as_cell", issue="43038")] + #[stable(feature = "as_cell", since = "1.37.0")] pub fn from_mut(t: &mut T) -> &Cell { unsafe { &*(t as *mut T as *const Cell) @@ -543,7 +540,6 @@ impl Cell<[T]> { /// # Examples /// /// ``` - /// #![feature(as_cell)] /// use std::cell::Cell; /// /// let slice: &mut [i32] = &mut [1, 2, 3]; @@ -552,7 +548,7 @@ impl Cell<[T]> { /// /// assert_eq!(slice_cell.len(), 3); /// ``` - #[unstable(feature = "as_cell", issue="43038")] + #[stable(feature = "as_cell", since = "1.37.0")] pub fn as_slice_of_cells(&self) -> &[Cell] { unsafe { &*(self as *const Cell<[T]> as *const [Cell]) @@ -969,7 +965,6 @@ impl RefCell { /// # Examples /// /// ``` - /// #![feature(borrow_state)] /// use std::cell::RefCell; /// /// let c = RefCell::new(5); @@ -984,7 +979,7 @@ impl RefCell { /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok()); /// } /// ``` - #[unstable(feature = "borrow_state", issue = "27733")] + #[stable(feature = "borrow_state", since = "1.37.0")] #[inline] pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { if !is_writing(self.borrow.get()) { @@ -1354,7 +1349,7 @@ impl<'b> BorrowRefMut<'b> { } } - // Clone a `BorrowRefMut`. + // Clones a `BorrowRefMut`. // // This is only valid if each `BorrowRefMut` is used to track a mutable // reference to a distinct, nonoverlapping range of the original object. diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index ec9ac7ce8b..0a870c6751 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -123,7 +123,7 @@ impl From for u32 { } } -/// Maps a byte in 0x00...0xFF to a `char` whose code point has the same value, in U+0000 to U+00FF. +/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF. /// /// Unicode is designed such that this effectively decodes bytes /// with the character encoding that IANA calls ISO-8859-1. diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index 18557e0c11..e843303380 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -337,16 +337,16 @@ impl char { /// ``` /// // as chars /// let eastern = '東'; - /// let capitol = '京'; + /// let capital = '京'; /// /// // both can be represented as three bytes /// assert_eq!(3, eastern.len_utf8()); - /// assert_eq!(3, capitol.len_utf8()); + /// assert_eq!(3, capital.len_utf8()); /// /// // as a &str, these two are encoded in UTF-8 /// let tokyo = "東京"; /// - /// let len = eastern.len_utf8() + capitol.len_utf8(); + /// let len = eastern.len_utf8() + capital.len_utf8(); /// /// // we can see that they take six bytes total... /// assert_eq!(6, tokyo.len()); @@ -1042,8 +1042,8 @@ impl char { /// Checks if the value is an ASCII alphabetic character: /// - /// - U+0041 'A' ... U+005A 'Z', or - /// - U+0061 'a' ... U+007A 'z'. + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z'. /// /// # Examples /// @@ -1075,7 +1075,7 @@ impl char { } /// Checks if the value is an ASCII uppercase character: - /// U+0041 'A' ... U+005A 'Z'. + /// U+0041 'A' ..= U+005A 'Z'. /// /// # Examples /// @@ -1107,7 +1107,7 @@ impl char { } /// Checks if the value is an ASCII lowercase character: - /// U+0061 'a' ... U+007A 'z'. + /// U+0061 'a' ..= U+007A 'z'. /// /// # Examples /// @@ -1140,9 +1140,9 @@ impl char { /// Checks if the value is an ASCII alphanumeric character: /// - /// - U+0041 'A' ... U+005A 'Z', or - /// - U+0061 'a' ... U+007A 'z', or - /// - U+0030 '0' ... U+0039 '9'. + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z', or + /// - U+0030 '0' ..= U+0039 '9'. /// /// # Examples /// @@ -1174,7 +1174,7 @@ impl char { } /// Checks if the value is an ASCII decimal digit: - /// U+0030 '0' ... U+0039 '9'. + /// U+0030 '0' ..= U+0039 '9'. /// /// # Examples /// @@ -1207,9 +1207,9 @@ impl char { /// Checks if the value is an ASCII hexadecimal digit: /// - /// - U+0030 '0' ... U+0039 '9', or - /// - U+0041 'A' ... U+0046 'F', or - /// - U+0061 'a' ... U+0066 'f'. + /// - U+0030 '0' ..= U+0039 '9', or + /// - U+0041 'A' ..= U+0046 'F', or + /// - U+0061 'a' ..= U+0066 'f'. /// /// # Examples /// @@ -1242,10 +1242,10 @@ impl char { /// Checks if the value is an ASCII punctuation character: /// - /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or - /// - U+003A ... U+0040 `: ; < = > ? @`, or - /// - U+005B ... U+0060 ``[ \ ] ^ _ ` ``, or - /// - U+007B ... U+007E `{ | } ~` + /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or + /// - U+003A ..= U+0040 `: ; < = > ? @`, or + /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or + /// - U+007B ..= U+007E `{ | } ~` /// /// # Examples /// @@ -1277,7 +1277,7 @@ impl char { } /// Checks if the value is an ASCII graphic character: - /// U+0021 '!' ... U+007E '~'. + /// U+0021 '!' ..= U+007E '~'. /// /// # Examples /// @@ -1358,7 +1358,7 @@ impl char { } /// Checks if the value is an ASCII control character: - /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE. + /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE. /// Note that most ASCII whitespace characters are control /// characters, but SPACE is not. /// diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index b3ff447be5..a697b7bd6e 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -129,7 +129,7 @@ pub const fn identity(x: T) -> T { x } /// # Examples /// /// By using trait bounds we can accept arguments of different types as long as they can be -/// converted a the specified type `T`. +/// converted to the specified type `T`. /// /// For example: By creating a generic function that takes an `AsRef` we express that we /// want to accept all references that can be converted to `&str` as an argument. @@ -177,8 +177,8 @@ pub trait AsRef { /// /// Using `AsMut` as trait bound for a generic function we can accept all mutable references /// that can be converted to type `&mut T`. Because [`Box`] implements `AsMut` we can -/// write a function `add_one`that takes all arguments that can be converted to `&mut u64`. -/// Because [`Box`] implements `AsMut` `add_one` accepts arguments of type +/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`. +/// Because [`Box`] implements `AsMut`, `add_one` accepts arguments of type /// `&mut Box` as well: /// /// ``` @@ -202,9 +202,9 @@ pub trait AsMut { /// A value-to-value conversion that consumes the input value. The /// opposite of [`From`]. /// -/// One should only implement `Into` if a conversion to a type outside the current crate is -/// required. Otherwise one should always prefer implementing [`From`] over `Into` because -/// implementing [`From`] automatically provides one with a implementation of `Into` thanks to +/// One should only implement [`Into`] if a conversion to a type outside the current crate is +/// required. Otherwise one should always prefer implementing [`From`] over [`Into`] because +/// implementing [`From`] automatically provides one with a implementation of [`Into`] thanks to /// the blanket implementation in the standard library. [`From`] cannot do these type of /// conversions because of Rust's orphaning rules. /// @@ -213,9 +213,9 @@ pub trait AsMut { /// # Generic Implementations /// /// - [`From`]` for U` implies `Into for T` -/// - `Into` is reflexive, which means that `Into for T` is implemented +/// - [`Into`] is reflexive, which means that `Into for T` is implemented /// -/// # Implementing `Into` for conversions to external types +/// # Implementing [`Into`] for conversions to external types /// /// If the destination type is not part of the current crate /// then you can't implement [`From`] directly. @@ -231,7 +231,7 @@ pub trait AsMut { /// ``` /// This will fail to compile because we cannot implement a trait for a type /// if both the trait and the type are not defined by the current crate. -/// This is due to Rust's orphaning rules. To bypass this, you can implement `Into` directly: +/// This is due to Rust's orphaning rules. To bypass this, you can implement [`Into`] directly: /// /// ``` /// struct Wrapper(Vec); @@ -242,19 +242,19 @@ pub trait AsMut { /// } /// ``` /// -/// It is important to understand that `Into` does not provide a [`From`] implementation -/// (as [`From`] does with `Into`). Therefore, you should always try to implement [`From`] -/// and then fall back to `Into` if [`From`] can't be implemented. +/// It is important to understand that [`Into`] does not provide a [`From`] implementation +/// (as [`From`] does with [`Into`]). Therefore, you should always try to implement [`From`] +/// and then fall back to [`Into`] if [`From`] can't be implemented. /// -/// Prefer using `Into` over [`From`] when specifying trait bounds on a generic function -/// to ensure that types that only implement `Into` can be used as well. +/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function +/// to ensure that types that only implement [`Into`] can be used as well. /// /// # Examples /// /// [`String`] implements `Into>`: /// /// In order to express that we want a generic function to take all arguments that can be -/// converted to a specified type `T`, we can use a trait bound of `Into`. +/// converted to a specified type `T`, we can use a trait bound of [`Into`]``. /// For example: The function `is_hello` takes all arguments that can be converted into a /// `Vec`. /// @@ -273,7 +273,7 @@ pub trait AsMut { /// [`Result`]: ../../std/result/enum.Result.html /// [`String`]: ../../std/string/struct.String.html /// [`From`]: trait.From.html -/// [`into`]: trait.Into.html#tymethod.into +/// [`Into`]: trait.Into.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 2906e5824a..49090fb8e4 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -5,6 +5,8 @@ //! Utilities related to FFI bindings. use crate::fmt; +use crate::marker::PhantomData; +use crate::ops::{Deref, DerefMut}; /// Equivalent to C's `void` type when used as a [pointer]. /// @@ -45,25 +47,33 @@ impl fmt::Debug for c_void { } /// Basic implementation of a `va_list`. +// The name is WIP, using `VaListImpl` for now. #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), windows))] +#[repr(transparent)] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930")] -extern { - type VaListImpl; +#[lang = "va_list"] +pub struct VaListImpl<'f> { + ptr: *mut c_void, + _marker: PhantomData<&'f c_void>, } #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), windows))] -impl fmt::Debug for VaListImpl { +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +impl<'f> fmt::Debug for VaListImpl<'f> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "va_list* {:p}", self) + write!(f, "va_list* {:p}", self.ptr) } } @@ -79,12 +89,14 @@ impl fmt::Debug for VaListImpl { reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930")] -struct VaListImpl { +#[lang = "va_list"] +pub struct VaListImpl<'f> { stack: *mut c_void, gr_top: *mut c_void, vr_top: *mut c_void, gr_offs: i32, vr_offs: i32, + _marker: PhantomData<&'f c_void>, } /// PowerPC ABI implementation of a `va_list`. @@ -95,12 +107,14 @@ struct VaListImpl { reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930")] -struct VaListImpl { +#[lang = "va_list"] +pub struct VaListImpl<'f> { gpr: u8, fpr: u8, reserved: u16, overflow_arg_area: *mut c_void, reg_save_area: *mut c_void, + _marker: PhantomData<&'f c_void>, } /// x86_64 ABI implementation of a `va_list`. @@ -111,22 +125,131 @@ struct VaListImpl { reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930")] -struct VaListImpl { +#[lang = "va_list"] +pub struct VaListImpl<'f> { gp_offset: i32, fp_offset: i32, overflow_arg_area: *mut c_void, reg_save_area: *mut c_void, + _marker: PhantomData<&'f c_void>, } -/// A wrapper for a `va_list` +/// asm.js ABI implementation of a `va_list`. +// asm.js uses the PNaCl ABI, which specifies that a `va_list` is +// an array of 4 32-bit integers, according to the old PNaCl docs at +// https://web.archive.org/web/20130518054430/https://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Derived-Types +// and clang does the same in `CreatePNaClABIBuiltinVaListDecl` from `lib/AST/ASTContext.cpp` +#[cfg(all(target_arch = "asmjs", not(windows)))] +#[repr(C)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] #[lang = "va_list"] -#[derive(Debug)] +pub struct VaListImpl<'f> { + inner: [crate::mem::MaybeUninit; 4], + _marker: PhantomData<&'f c_void>, +} + +#[cfg(all(target_arch = "asmjs", not(windows)))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930")] +impl<'f> fmt::Debug for VaListImpl<'f> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + write!(f, "va_list* [{:#x}, {:#x}, {:#x}, {:#x}]", + self.inner[0].read(), self.inner[1].read(), + self.inner[2].read(), self.inner[3].read()) + } + } +} + +/// A wrapper for a `va_list` #[repr(transparent)] -pub struct VaList<'a>(&'a mut VaListImpl); +#[derive(Debug)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +pub struct VaList<'a, 'f: 'a> { + #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), + all(target_arch = "aarch64", target_os = "ios"), + windows))] + inner: VaListImpl<'f>, + + #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", + target_arch = "x86_64", target_arch = "asmjs"), + any(not(target_arch = "aarch64"), not(target_os = "ios")), + not(windows)))] + inner: &'a mut VaListImpl<'f>, + + _marker: PhantomData<&'a mut VaListImpl<'f>>, +} + +#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), + all(target_arch = "aarch64", target_os = "ios"), + windows))] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +impl<'f> VaListImpl<'f> { + /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { + inner: VaListImpl { ..*self }, + _marker: PhantomData, + } + } +} + +#[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", + target_arch = "x86_64", target_arch = "asmjs"), + any(not(target_arch = "aarch64"), not(target_os = "ios")), + not(windows)))] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +impl<'f> VaListImpl<'f> { + /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { + inner: self, + _marker: PhantomData, + } + } +} + +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +impl<'a, 'f: 'a> Deref for VaList<'a, 'f> { + type Target = VaListImpl<'f>; + + #[inline] + fn deref(&self) -> &VaListImpl<'f> { + &self.inner + } +} + +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> { + #[inline] + fn deref_mut(&mut self) -> &mut VaListImpl<'f> { + &mut self.inner + } +} // The VaArgSafe trait needs to be used in public interfaces, however, the trait // itself must not be allowed to be used outside this module. Allowing users to @@ -175,56 +298,76 @@ impl sealed_trait::VaArgSafe for *mut T {} issue = "44930")] impl sealed_trait::VaArgSafe for *const T {} -impl<'a> VaList<'a> { +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +#[cfg(not(bootstrap))] +impl<'f> VaListImpl<'f> { /// Advance to the next arg. - #[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] + #[inline] pub unsafe fn arg(&mut self) -> T { va_arg(self) } /// Copies the `va_list` at the current location. - #[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] pub unsafe fn with_copy(&self, f: F) -> R - where F: for<'copy> FnOnce(VaList<'copy>) -> R { - #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), - all(target_arch = "aarch64", target_os = "ios"), - windows))] - let mut ap = va_copy(self); - #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), - not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))] - let mut ap_inner = va_copy(self); - #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), - not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))] - let mut ap = VaList(&mut ap_inner); - let ret = f(VaList(ap.0)); + where F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R { + let mut ap = self.clone(); + let ret = f(ap.as_va_list()); va_end(&mut ap); ret } } +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +#[cfg(not(bootstrap))] +impl<'f> Clone for VaListImpl<'f> { + #[inline] + fn clone(&self) -> Self { + let mut dest = crate::mem::MaybeUninit::uninit(); + unsafe { + va_copy(dest.as_mut_ptr(), self); + dest.assume_init() + } + } +} + +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +#[cfg(not(bootstrap))] +impl<'f> Drop for VaListImpl<'f> { + fn drop(&mut self) { + // FIXME: this should call `va_end`, but there's no clean way to + // guarantee that `drop` always gets inlined into its caller, + // so the `va_end` would get directly called from the same function as + // the corresponding `va_copy`. `man va_end` states that C requires this, + // and LLVM basically follows the C semantics, so we need to make sure + // that `va_end` is always called from the same function as `va_copy`. + // For more details, see https://github.com/rust-lang/rust/pull/59625 + // and https://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic. + // + // This works for now, since `va_end` is a no-op on all current LLVM targets. + } +} + extern "rust-intrinsic" { /// Destroy the arglist `ap` after initialization with `va_start` or /// `va_copy`. - fn va_end(ap: &mut VaList<'_>); + #[cfg(not(bootstrap))] + fn va_end(ap: &mut VaListImpl<'_>); /// Copies the current location of arglist `src` to the arglist `dst`. - #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), - all(target_arch = "aarch64", target_os = "ios"), - windows))] - fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>; - #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), - not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))] - fn va_copy(src: &VaList<'_>) -> VaListImpl; + #[cfg(not(bootstrap))] + fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>); /// Loads an argument of type `T` from the `va_list` `ap` and increment the /// argument `ap` points to. - fn va_arg(ap: &mut VaList<'_>) -> T; + #[cfg(not(bootstrap))] + fn va_arg(ap: &mut VaListImpl<'_>) -> T; } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 2f6d745d14..17ea584388 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -2070,19 +2070,19 @@ macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name:Debug),*> Debug for ($($name,)*) where last_type!($($name,)+): ?Sized { + impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case, unused_assignments)] fn fmt(&self, f: &mut Formatter<'_>) -> Result { let mut builder = f.debug_tuple(""); - let ($(ref $name,)*) = *self; + let ($(ref $name,)+) = *self; $( builder.field(&$name); - )* + )+ builder.finish() } } - peel! { $($name,)* } + peel! { $($name,)+ } ) } diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 3f76ac2019..acca8d7ba1 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -21,10 +21,11 @@ use crate::task::{Context, Poll}; /// task. /// /// When using a future, you generally won't call `poll` directly, but instead -/// `await!` the value. +/// `.await` the value. #[doc(spotlight)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] +#[cfg_attr(not(bootstrap), lang = "future_trait")] pub trait Future { /// The type of value produced on completion. #[stable(feature = "futures_api", since = "1.36.0")] diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 98150fd9f8..38e3864284 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -617,11 +617,11 @@ mod impls { ( $($name:ident)+) => ( #[stable(feature = "rust1", since = "1.0.0")] - impl<$($name: Hash),*> Hash for ($($name,)*) where last_type!($($name,)+): ?Sized { + impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case)] fn hash(&self, state: &mut S) { - let ($(ref $name,)*) = *self; - $($name.hash(state);)* + let ($(ref $name,)+) = *self; + $($name.hash(state);)+ } } ); diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 94eddbeda2..519212bb6c 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -111,31 +111,31 @@ pub fn spin_loop() { /// This function is a no-op, and does not even read from `dummy`. #[inline] #[unstable(feature = "test", issue = "27812")] +#[allow(unreachable_code)] // this makes #[cfg] a bit easier below. pub fn black_box(dummy: T) -> T { - cfg_if! { - if #[cfg(any( - target_arch = "asmjs", - all( - target_arch = "wasm32", - target_os = "emscripten" - ) - ))] { - #[inline] - unsafe fn black_box_impl(d: T) -> T { - // these targets do not support inline assembly - let ret = crate::ptr::read_volatile(&d); - crate::mem::forget(d); - ret - } - } else { - #[inline] - unsafe fn black_box_impl(d: T) -> T { - // we need to "use" the argument in some way LLVM can't - // introspect. - asm!("" : : "r"(&d)); - d - } - } + // We need to "use" the argument in some way LLVM can't introspect, and on + // targets that support it we can typically leverage inline assembly to do + // this. LLVM's intepretation of inline assembly is that it's, well, a black + // box. This isn't the greatest implementation since it probably deoptimizes + // more than we want, but it's so far good enough. + #[cfg(not(any( + target_arch = "asmjs", + all( + target_arch = "wasm32", + target_os = "emscripten" + ) + )))] + unsafe { + asm!("" : : "r"(&dummy)); + return dummy; + } + + // Not all platforms support inline assembly so try to do something without + // inline assembly which in theory still hinders at least some optimizations + // on those targets. This is the "best effort" scenario. + unsafe { + let ret = crate::ptr::read_volatile(&dummy); + crate::mem::forget(dummy); + ret } - unsafe { black_box_impl(dummy) } } diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index dd5b92857b..3acf2ec837 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -117,84 +117,3 @@ macro_rules! impl_fn_for_zst { )+ } } - -/// A macro for defining `#[cfg]` if-else statements. -/// -/// The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C -/// preprocessor macro by allowing definition of a cascade of `#[cfg]` cases, -/// emitting the implementation which matches first. -/// -/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code -/// without having to rewrite each clause multiple times. -/// -/// # Example -/// -/// ``` -/// #[macro_use] -/// extern crate cfg_if; -/// -/// cfg_if! { -/// if #[cfg(unix)] { -/// fn foo() { /* unix specific functionality */ } -/// } else if #[cfg(target_pointer_width = "32")] { -/// fn foo() { /* non-unix, 32-bit functionality */ } -/// } else { -/// fn foo() { /* fallback implementation */ } -/// } -/// } -/// -/// # fn main() {} -/// ``` -macro_rules! cfg_if { - // match if/else chains with a final `else` - ($( - if #[cfg($($meta:meta),*)] { $($it:item)* } - ) else * else { - $($it2:item)* - }) => { - cfg_if! { - @__items - () ; - $( ( ($($meta),*) ($($it)*) ), )* - ( () ($($it2)*) ), - } - }; - - // match if/else chains lacking a final `else` - ( - if #[cfg($($i_met:meta),*)] { $($i_it:item)* } - $( - else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } - )* - ) => { - cfg_if! { - @__items - () ; - ( ($($i_met),*) ($($i_it)*) ), - $( ( ($($e_met),*) ($($e_it)*) ), )* - ( () () ), - } - }; - - // Internal and recursive macro to emit all the items - // - // Collects all the negated cfgs in a list at the beginning and after the - // semicolon is all the remaining items - (@__items ($($not:meta,)*) ; ) => {}; - (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { - // Emit all items within one block, applying an approprate #[cfg]. The - // #[cfg] will require all `$m` matchers specified and must also negate - // all previous matchers. - cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } - - // Recurse to emit all other items in `$rest`, and when we do so add all - // our `$m` matchers to the list of `$not` matchers as future emissions - // will have to negate everything we just matched as well. - cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } - }; - - // Internal macro to Apply a cfg attribute to a list of items - (@__apply $m:meta, $($it:item)*) => { - $(#[$m] $it)* - }; -} diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 782a7ba455..b30eff8baa 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1051,6 +1051,19 @@ extern "rust-intrinsic" { /// Returns the absolute value of an `f64`. pub fn fabsf64(x: f64) -> f64; + /// Returns the minimum of two `f32` values. + #[cfg(not(bootstrap))] + pub fn minnumf32(x: f32, y: f32) -> f32; + /// Returns the minimum of two `f64` values. + #[cfg(not(bootstrap))] + pub fn minnumf64(x: f64, y: f64) -> f64; + /// Returns the maximum of two `f32` values. + #[cfg(not(bootstrap))] + pub fn maxnumf32(x: f32, y: f32) -> f32; + /// Returns the maximum of two `f64` values. + #[cfg(not(bootstrap))] + pub fn maxnumf64(x: f64, y: f64) -> f64; + /// Copies the sign from `y` to `x` for `f32` values. pub fn copysignf32(x: f32, y: f32) -> f32; /// Copies the sign from `y` to `x` for `f64` values. @@ -1240,6 +1253,21 @@ extern "rust-intrinsic" { /// y < 0 or y >= N, where N is the width of T in bits. pub fn unchecked_shr(x: T, y: T) -> T; + /// Returns the result of an unchecked addition, resulting in + /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`. + #[cfg(not(bootstrap))] + pub fn unchecked_add(x: T, y: T) -> T; + + /// Returns the result of an unchecked substraction, resulting in + /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`. + #[cfg(not(bootstrap))] + pub fn unchecked_sub(x: T, y: T) -> T; + + /// Returns the result of an unchecked multiplication, resulting in + /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`. + #[cfg(not(bootstrap))] + pub fn unchecked_mul(x: T, y: T) -> T; + /// Performs rotate left. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, @@ -1298,30 +1326,10 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); } -mod real_intrinsics { - extern "rust-intrinsic" { - /// Copies `count * size_of::()` bytes from `src` to `dst`. The source - /// and destination must *not* overlap. - /// For the full docs, see the stabilized wrapper [`copy_nonoverlapping`]. - /// - /// [`copy_nonoverlapping`]: ../../std/ptr/fn.copy_nonoverlapping.html - pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); - - /// Copies `count * size_of::()` bytes from `src` to `dst`. The source - /// and destination may overlap. - /// For the full docs, see the stabilized wrapper [`copy`]. - /// - /// [`copy`]: ../../std/ptr/fn.copy.html - pub fn copy(src: *const T, dst: *mut T, count: usize); - - /// Sets `count * size_of::()` bytes of memory starting at `dst` to - /// `val`. - /// For the full docs, see the stabilized wrapper [`write_bytes`]. - /// - /// [`write_bytes`]: ../../std/ptr/fn.write_bytes.html - pub fn write_bytes(dst: *mut T, val: u8, count: usize); - } -} +// Some functions are defined here because they accidentally got made +// available in this module on stable. See . +// (`transmute` also falls into this category, but it cannot be wrapped due to the +// check that `T` and `U` have the same size.) /// Copies `count * size_of::()` bytes from `src` to `dst`. The source /// and destination must *not* overlap. @@ -1409,7 +1417,10 @@ mod real_intrinsics { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { - real_intrinsics::copy_nonoverlapping(src, dst, count); + extern "rust-intrinsic" { + fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + } + copy_nonoverlapping(src, dst, count); } /// Copies `count * size_of::()` bytes from `src` to `dst`. The source @@ -1466,7 +1477,10 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { - real_intrinsics::copy(src, dst, count) + extern "rust-intrinsic" { + fn copy(src: *const T, dst: *mut T, count: usize); + } + copy(src, dst, count) } /// Sets `count * size_of::()` bytes of memory starting at `dst` to @@ -1544,5 +1558,58 @@ pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { - real_intrinsics::write_bytes(dst, val, count) + extern "rust-intrinsic" { + fn write_bytes(dst: *mut T, val: u8, count: usize); + } + write_bytes(dst, val, count) +} + +// Simple bootstrap implementations of minnum/maxnum for stage0 compilation. + +/// Returns the minimum of two `f32` values. +#[cfg(bootstrap)] +pub fn minnumf32(x: f32, y: f32) -> f32 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signaling NaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if x < y || y != y { x } else { y }) * 1.0 +} + +/// Returns the minimum of two `f64` values. +#[cfg(bootstrap)] +pub fn minnumf64(x: f64, y: f64) -> f64 { + // Identical to the `f32` case. + (if x < y || y != y { x } else { y }) * 1.0 +} + +/// Returns the maximum of two `f32` values. +#[cfg(bootstrap)] +pub fn maxnumf32(x: f32, y: f32) -> f32 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signaling NaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if x < y || x != x { y } else { x }) * 1.0 +} + +/// Returns the maximum of two `f64` values. +#[cfg(bootstrap)] +pub fn maxnumf64(x: f64, y: f64) -> f64 { + // Identical to the `f32` case. + (if x < y || x != x { y } else { x }) * 1.0 +} + +/// For bootstrapping, implement unchecked_sub as just wrapping_sub. +#[cfg(bootstrap)] +pub unsafe fn unchecked_sub(x: T, y: T) -> T { + sub_with_overflow(x, y).0 } diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 518442efe7..c2edcd22f9 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1509,6 +1509,20 @@ impl DoubleEndedIterator for Skip where I: DoubleEndedIterator + ExactSize } } + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n < len { + self.iter.nth_back(n) + } else { + if len > 0 { + // consume the original iterator + self.iter.nth_back(len-1); + } + None + } + } + fn try_rfold(&mut self, init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 1601357d3b..6eccb9d1ea 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -140,6 +140,11 @@ //! call `next()` on your iterator, until it reaches `None`. Let's go over that //! next. //! +//! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold` +//! which call `next` internally. However, it is also possible to write a custom implementation of +//! methods like `nth` and `fold` if an iterator can compute them more efficiently without calling +//! `next`. +//! //! # for Loops and IntoIterator //! //! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index f8a975cc8d..efda3b263c 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -34,6 +34,13 @@ pub trait Step: Clone + PartialOrd + Sized { /// Adds a `usize`, returning `None` on overflow. fn add_usize(&self, n: usize) -> Option; + + /// Subtracts a `usize`, returning `None` on underflow. + fn sub_usize(&self, n: usize) -> Option { + // this default implementation makes the addition of `sub_usize` a non-breaking change + let _ = n; + unimplemented!() + } } // These are still macro-generated because the integer literals resolve to different types. @@ -85,6 +92,15 @@ macro_rules! step_impl_unsigned { } } + #[inline] + #[allow(unreachable_patterns)] + fn sub_usize(&self, n: usize) -> Option { + match <$t>::try_from(n) { + Ok(n_as_t) => self.checked_sub(n_as_t), + Err(_) => None, + } + } + step_identical_methods!(); } )*) @@ -125,6 +141,25 @@ macro_rules! step_impl_signed { } } + #[inline] + #[allow(unreachable_patterns)] + fn sub_usize(&self, n: usize) -> Option { + match <$unsigned>::try_from(n) { + Ok(n_as_unsigned) => { + // Wrapping in unsigned space handles cases like + // `80_i8.sub_usize(200) == Some(-120_i8)`, + // even though 200_usize is out of range for i8. + let wrapped = (*self as $unsigned).wrapping_sub(n_as_unsigned) as $t; + if wrapped <= *self { + Some(wrapped) + } else { + None // Subtraction underflowed + } + } + Err(_) => None, + } + } + step_identical_methods!(); } )*) @@ -246,6 +281,19 @@ impl DoubleEndedIterator for ops::Range { None } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + if let Some(minus_n) = self.end.sub_usize(n) { + if minus_n > self.start { + self.end = minus_n.sub_one(); + return Some(self.end.clone()) + } + } + + self.end = self.start.clone(); + None + } } #[stable(feature = "fused", since = "1.26.0")] @@ -403,6 +451,34 @@ impl DoubleEndedIterator for ops::RangeInclusive { }) } + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.compute_is_empty(); + if self.is_empty.unwrap_or_default() { + return None; + } + + if let Some(minus_n) = self.end.sub_usize(n) { + use crate::cmp::Ordering::*; + + match minus_n.partial_cmp(&self.start) { + Some(Greater) => { + self.is_empty = Some(false); + self.end = minus_n.sub_one(); + return Some(minus_n); + } + Some(Equal) => { + self.is_empty = Some(true); + return Some(minus_n); + } + _ => {} + } + } + + self.is_empty = Some(true); + None + } + #[inline] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index 7815fe9c59..adfb639bae 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -72,10 +72,10 @@ macro_rules! integer_sum_product { ($($a:ty)*) => ( integer_sum_product!(@impls 0, 1, #[stable(feature = "iter_arith_traits", since = "1.12.0")], - $($a)+); + $($a)*); integer_sum_product!(@impls Wrapping(0), Wrapping(1), #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], - $(Wrapping<$a>)+); + $(Wrapping<$a>)*); ); } @@ -223,3 +223,113 @@ impl Product> for Result ResultShunt::process(iter, |i| i.product()) } } + +/// An iterator adapter that produces output as long as the underlying +/// iterator produces `Option::Some` values. +struct OptionShunt { + iter: I, + exited_early: bool, +} + +impl OptionShunt +where + I: Iterator>, +{ + /// Process the given iterator as if it yielded a `T` instead of a + /// `Option`. Any `None` value will stop the inner iterator and + /// the overall result will be a `None`. + pub fn process(iter: I, mut f: F) -> Option + where + F: FnMut(&mut Self) -> U, + { + let mut shunt = OptionShunt::new(iter); + let value = f(shunt.by_ref()); + shunt.reconstruct(value) + } + + fn new(iter: I) -> Self { + OptionShunt { + iter, + exited_early: false, + } + } + + /// Consume the adapter and rebuild a `Option` value. + fn reconstruct(self, val: U) -> Option { + if self.exited_early { + None + } else { + Some(val) + } + } +} + +impl Iterator for OptionShunt +where + I: Iterator>, +{ + type Item = T; + + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Some(v)) => Some(v), + Some(None) => { + self.exited_early = true; + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.exited_early { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.37.0")] +impl Sum> for Option +where + T: Sum, +{ + /// Takes each element in the `Iterator`: if it is a `None`, no further + /// elements are taken, and the `None` is returned. Should no `None` occur, + /// the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up the position of the character 'a' in a vector of strings, + /// if a word did not have the character 'a' the operation returns `None`: + /// + /// ``` + /// let words = vec!["have", "a", "great", "day"]; + /// let total: Option = words.iter().map(|w| w.find('a')).sum(); + /// assert_eq!(total, Some(5)); + /// ``` + fn sum(iter: I) -> Option + where + I: Iterator>, + { + OptionShunt::process(iter, |i| i.sum()) + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.37.0")] +impl Product> for Option +where + T: Product, +{ + /// Takes each element in the `Iterator`: if it is a `None`, no further + /// elements are taken, and the `None` is returned. Should no `None` occur, + /// the product of all elements is returned. + fn product(iter: I) -> Option + where + I: Iterator>, + { + OptionShunt::process(iter, |i| i.product()) + } +} diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index cd61ab5c55..1865160bc3 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -196,7 +196,7 @@ pub trait FromIterator: Sized { /// ```rust /// fn collect_as_strings(collection: T) -> Vec /// where T: IntoIterator, -/// T::Item : std::fmt::Debug, +/// T::Item: std::fmt::Debug, /// { /// collection /// .into_iter() diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs index 06de95c082..2c1aeb5690 100644 --- a/src/libcore/iter/traits/double_ended.rs +++ b/src/libcore/iter/traits/double_ended.rs @@ -88,7 +88,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_nth_back)] /// let a = [1, 2, 3]; /// assert_eq!(a.iter().nth_back(2), Some(&1)); /// ``` @@ -96,7 +95,6 @@ pub trait DoubleEndedIterator: Iterator { /// Calling `nth_back()` multiple times doesn't rewind the iterator: /// /// ``` - /// #![feature(iter_nth_back)] /// let a = [1, 2, 3]; /// /// let mut iter = a.iter(); @@ -108,12 +106,11 @@ pub trait DoubleEndedIterator: Iterator { /// Returning `None` if there are less than `n + 1` elements: /// /// ``` - /// #![feature(iter_nth_back)] /// let a = [1, 2, 3]; /// assert_eq!(a.iter().nth_back(10), None); /// ``` #[inline] - #[unstable(feature = "iter_nth_back", issue = "56995")] + #[stable(feature = "iter_nth_back", since = "1.37.0")] fn nth_back(&mut self, mut n: usize) -> Option { for x in self.rev() { if n == 0 { return Some(x) } diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 38c7c9bc4d..30923c7414 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -964,6 +964,7 @@ pub trait Iterator { /// Creates an iterator that skips the first `n` elements. /// /// After they have been consumed, the rest of the elements are yielded. + /// Rather than overriding this method directly, instead override the `nth` method. /// /// # Examples /// @@ -1494,13 +1495,13 @@ pub trait Iterator { let mut left: B = Default::default(); let mut right: B = Default::default(); - for x in self { + self.for_each(|x| { if f(&x) { left.extend(Some(x)) } else { right.extend(Some(x)) } - } + }); (left, right) } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4a70329b64..04c50329de 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -69,12 +69,11 @@ #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] #![feature(asm)] -#![feature(associated_type_defaults)] +#![feature(bound_cloned)] #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] #![feature(const_fn)] #![feature(const_fn_union)] -#![feature(custom_attribute)] #![feature(doc_cfg)] #![feature(doc_spotlight)] #![feature(extern_types)] @@ -100,6 +99,7 @@ #![feature(staged_api)] #![feature(std_internals)] #![feature(stmt_expr_attributes)] +#![cfg_attr(not(bootstrap), feature(transparent_unions))] #![feature(unboxed_closures)] #![feature(unsized_locals)] #![feature(untagged_unions)] @@ -120,7 +120,6 @@ #![feature(const_str_len)] #![feature(const_int_conversion)] #![feature(const_transmute)] -#![feature(reverse_bits)] #![feature(non_exhaustive)] #![feature(structural_match)] #![feature(abi_unadjusted)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index cfe85c0c46..589061b282 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -15,7 +15,7 @@ macro_rules! panic { $crate::panic!($msg) ); ($fmt:expr, $($arg:tt)+) => ({ - $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), + $crate::panicking::panic_fmt(format_args!($fmt, $($arg)+), &(file!(), line!(), __rust_unstable_column!())) }); } @@ -445,9 +445,10 @@ macro_rules! writeln { /// * Iterators that dynamically terminate. /// /// If the determination that the code is unreachable proves incorrect, the -/// program immediately terminates with a [`panic!`]. The function [`unreachable_unchecked`], -/// which belongs to the [`std::hint`] module, informs the compiler to -/// optimize the code out of the release version entirely. +/// program immediately terminates with a [`panic!`]. +/// +/// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which +/// will cause undefined behavior if the code is reached. /// /// [`panic!`]: ../std/macro.panic.html /// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html @@ -557,7 +558,7 @@ macro_rules! unreachable { #[stable(feature = "rust1", since = "1.0.0")] macro_rules! unimplemented { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); + ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); } /// Indicates unfinished code. @@ -616,7 +617,7 @@ macro_rules! unimplemented { #[unstable(feature = "todo_macro", issue = "59277")] macro_rules! todo { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); + ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); } /// Creates an array of [`MaybeUninit`]. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d7cfccae29..d9757d78dc 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -103,7 +103,7 @@ pub trait Sized { /// `Unsize` is implemented for: /// /// - `[T; N]` is `Unsize<[T]>` -/// - `T` is `Unsize` when `T: Trait` +/// - `T` is `Unsize` when `T: Trait` /// - `Foo<..., T, ...>` is `Unsize>` if: /// - `T: Unsize` /// - Foo is a struct diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs deleted file mode 100644 index a11ff5e075..0000000000 --- a/src/libcore/mem.rs +++ /dev/null @@ -1,1403 +0,0 @@ -//! Basic functions for dealing with memory. -//! -//! This module contains functions for querying the size and alignment of -//! types, initializing and manipulating memory. - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::clone; -use crate::cmp; -use crate::fmt; -use crate::hash; -use crate::intrinsics; -use crate::marker::{Copy, PhantomData, Sized}; -use crate::ptr; -use crate::ops::{Deref, DerefMut}; - -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(inline)] -pub use crate::intrinsics::transmute; - -/// Takes ownership and "forgets" about the value **without running its destructor**. -/// -/// Any resources the value manages, such as heap memory or a file handle, will linger -/// forever in an unreachable state. However, it does not guarantee that pointers -/// to this memory will remain valid. -/// -/// * If you want to leak memory, see [`Box::leak`][leak]. -/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw]. -/// * If you want to dispose of a value properly, running its destructor, see -/// [`mem::drop`][drop]. -/// -/// # Safety -/// -/// `forget` is not marked as `unsafe`, because Rust's safety guarantees -/// do not include a guarantee that destructors will always run. For example, -/// a program can create a reference cycle using [`Rc`][rc], or call -/// [`process::exit`][exit] to exit without running destructors. Thus, allowing -/// `mem::forget` from safe code does not fundamentally change Rust's safety -/// guarantees. -/// -/// That said, leaking resources such as memory or I/O objects is usually undesirable, -/// so `forget` is only recommended for specialized use cases like those shown below. -/// -/// Because forgetting a value is allowed, any `unsafe` code you write must -/// allow for this possibility. You cannot return a value and expect that the -/// caller will necessarily run the value's destructor. -/// -/// [rc]: ../../std/rc/struct.Rc.html -/// [exit]: ../../std/process/fn.exit.html -/// -/// # Examples -/// -/// Leak an I/O object, never closing the file: -/// -/// ```no_run -/// use std::mem; -/// use std::fs::File; -/// -/// let file = File::open("foo.txt").unwrap(); -/// mem::forget(file); -/// ``` -/// -/// The practical use cases for `forget` are rather specialized and mainly come -/// up in unsafe or FFI code. -/// -/// [drop]: fn.drop.html -/// [uninit]: fn.uninitialized.html -/// [clone]: ../clone/trait.Clone.html -/// [swap]: fn.swap.html -/// [box]: ../../std/boxed/struct.Box.html -/// [leak]: ../../std/boxed/struct.Box.html#method.leak -/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw -/// [ub]: ../../reference/behavior-considered-undefined.html -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn forget(t: T) { - ManuallyDrop::new(t); -} - -/// Like [`forget`], but also accepts unsized values. -/// -/// This function is just a shim intended to be removed when the `unsized_locals` feature gets -/// stabilized. -/// -/// [`forget`]: fn.forget.html -#[inline] -#[unstable(feature = "forget_unsized", issue = "0")] -pub fn forget_unsized(t: T) { - unsafe { intrinsics::forget(t) } -} - -/// Returns the size of a type in bytes. -/// -/// More specifically, this is the offset in bytes between successive elements -/// in an array with that item type including alignment padding. Thus, for any -/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::()`. -/// -/// In general, the size of a type is not stable across compilations, but -/// specific types such as primitives are. -/// -/// The following table gives the size for primitives. -/// -/// Type | size_of::\() -/// ---- | --------------- -/// () | 0 -/// bool | 1 -/// u8 | 1 -/// u16 | 2 -/// u32 | 4 -/// u64 | 8 -/// u128 | 16 -/// i8 | 1 -/// i16 | 2 -/// i32 | 4 -/// i64 | 8 -/// i128 | 16 -/// f32 | 4 -/// f64 | 8 -/// char | 4 -/// -/// Furthermore, `usize` and `isize` have the same size. -/// -/// The types `*const T`, `&T`, `Box`, `Option<&T>`, and `Option>` all have -/// the same size. If `T` is Sized, all of those types have the same size as `usize`. -/// -/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` -/// have the same size. Likewise for `*const T` and `*mut T`. -/// -/// # Size of `#[repr(C)]` items -/// -/// The `C` representation for items has a defined layout. With this layout, -/// the size of items is also stable as long as all fields have a stable size. -/// -/// ## Size of Structs -/// -/// For `structs`, the size is determined by the following algorithm. -/// -/// For each field in the struct ordered by declaration order: -/// -/// 1. Add the size of the field. -/// 2. Round up the current size to the nearest multiple of the next field's [alignment]. -/// -/// Finally, round the size of the struct to the nearest multiple of its [alignment]. -/// The alignment of the struct is usually the largest alignment of all its -/// fields; this can be changed with the use of `repr(align(N))`. -/// -/// Unlike `C`, zero sized structs are not rounded up to one byte in size. -/// -/// ## Size of Enums -/// -/// Enums that carry no data other than the discriminant have the same size as C enums -/// on the platform they are compiled for. -/// -/// ## Size of Unions -/// -/// The size of a union is the size of its largest field. -/// -/// Unlike `C`, zero sized unions are not rounded up to one byte in size. -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// // Some primitives -/// assert_eq!(4, mem::size_of::()); -/// assert_eq!(8, mem::size_of::()); -/// assert_eq!(0, mem::size_of::<()>()); -/// -/// // Some arrays -/// assert_eq!(8, mem::size_of::<[i32; 2]>()); -/// assert_eq!(12, mem::size_of::<[i32; 3]>()); -/// assert_eq!(0, mem::size_of::<[i32; 0]>()); -/// -/// -/// // Pointer size equality -/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>()); -/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); -/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); -/// assert_eq!(mem::size_of::>(), mem::size_of::>>()); -/// ``` -/// -/// Using `#[repr(C)]`. -/// -/// ``` -/// use std::mem; -/// -/// #[repr(C)] -/// struct FieldStruct { -/// first: u8, -/// second: u16, -/// third: u8 -/// } -/// -/// // The size of the first field is 1, so add 1 to the size. Size is 1. -/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2. -/// // The size of the second field is 2, so add 2 to the size. Size is 4. -/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4. -/// // The size of the third field is 1, so add 1 to the size. Size is 5. -/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its -/// // fields is 2), so add 1 to the size for padding. Size is 6. -/// assert_eq!(6, mem::size_of::()); -/// -/// #[repr(C)] -/// struct TupleStruct(u8, u16, u8); -/// -/// // Tuple structs follow the same rules. -/// assert_eq!(6, mem::size_of::()); -/// -/// // Note that reordering the fields can lower the size. We can remove both padding bytes -/// // by putting `third` before `second`. -/// #[repr(C)] -/// struct FieldStructOptimized { -/// first: u8, -/// third: u8, -/// second: u16 -/// } -/// -/// assert_eq!(4, mem::size_of::()); -/// -/// // Union size is the size of the largest field. -/// #[repr(C)] -/// union ExampleUnion { -/// smaller: u8, -/// larger: u16 -/// } -/// -/// assert_eq!(2, mem::size_of::()); -/// ``` -/// -/// [alignment]: ./fn.align_of.html -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_promotable] -pub const fn size_of() -> usize { - intrinsics::size_of::() -} - -/// Returns the size of the pointed-to value in bytes. -/// -/// This is usually the same as `size_of::()`. However, when `T` *has* no -/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], -/// then `size_of_val` can be used to get the dynamically-known size. -/// -/// [slice]: ../../std/primitive.slice.html -/// [trait object]: ../../book/ch17-02-trait-objects.html -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// assert_eq!(4, mem::size_of_val(&5i32)); -/// -/// let x: [u8; 13] = [0; 13]; -/// let y: &[u8] = &x; -/// assert_eq!(13, mem::size_of_val(y)); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn size_of_val(val: &T) -> usize { - unsafe { intrinsics::size_of_val(val) } -} - -/// Returns the [ABI]-required minimum alignment of a type. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// # #![allow(deprecated)] -/// use std::mem; -/// -/// assert_eq!(4, mem::min_align_of::()); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] -pub fn min_align_of() -> usize { - intrinsics::min_align_of::() -} - -/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// # #![allow(deprecated)] -/// use std::mem; -/// -/// assert_eq!(4, mem::min_align_of_val(&5i32)); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")] -pub fn min_align_of_val(val: &T) -> usize { - unsafe { intrinsics::min_align_of_val(val) } -} - -/// Returns the [ABI]-required minimum alignment of a type. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// assert_eq!(4, mem::align_of::()); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_promotable] -pub const fn align_of() -> usize { - intrinsics::min_align_of::() -} - -/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// assert_eq!(4, mem::align_of_val(&5i32)); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn align_of_val(val: &T) -> usize { - unsafe { intrinsics::min_align_of_val(val) } -} - -/// Returns `true` if dropping values of type `T` matters. -/// -/// This is purely an optimization hint, and may be implemented conservatively: -/// it may return `true` for types that don't actually need to be dropped. -/// As such always returning `true` would be a valid implementation of -/// this function. However if this function actually returns `false`, then you -/// can be certain dropping `T` has no side effect. -/// -/// Low level implementations of things like collections, which need to manually -/// drop their data, should use this function to avoid unnecessarily -/// trying to drop all their contents when they are destroyed. This might not -/// make a difference in release builds (where a loop that has no side-effects -/// is easily detected and eliminated), but is often a big win for debug builds. -/// -/// Note that `ptr::drop_in_place` already performs this check, so if your workload -/// can be reduced to some small number of drop_in_place calls, using this is -/// unnecessary. In particular note that you can drop_in_place a slice, and that -/// will do a single needs_drop check for all the values. -/// -/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using -/// needs_drop explicitly. Types like HashMap, on the other hand, have to drop -/// values one at a time and should use this API. -/// -/// -/// # Examples -/// -/// Here's an example of how a collection might make use of needs_drop: -/// -/// ``` -/// use std::{mem, ptr}; -/// -/// pub struct MyCollection { -/// # data: [T; 1], -/// /* ... */ -/// } -/// # impl MyCollection { -/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data } -/// # fn free_buffer(&mut self) {} -/// # } -/// -/// impl Drop for MyCollection { -/// fn drop(&mut self) { -/// unsafe { -/// // drop the data -/// if mem::needs_drop::() { -/// for x in self.iter_mut() { -/// ptr::drop_in_place(x); -/// } -/// } -/// self.free_buffer(); -/// } -/// } -/// } -/// ``` -#[inline] -#[stable(feature = "needs_drop", since = "1.21.0")] -pub const fn needs_drop() -> bool { - intrinsics::needs_drop::() -} - -/// Creates a value whose bytes are all zero. -/// -/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. -/// It is useful for FFI sometimes, but should generally be avoided. -/// -/// There is no guarantee that an all-zero byte-pattern represents a valid value of -/// some type `T`. For example, the all-zero byte-pattern is not a valid value -/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types -/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv] -/// that there always is a valid value in a variable it considers initialized. -/// -/// [zeroed]: union.MaybeUninit.html#method.zeroed -/// [ub]: ../../reference/behavior-considered-undefined.html -/// [inv]: union.MaybeUninit.html#initialization-invariant -/// -/// # Examples -/// -/// Correct usage of this function: initializing an integer with zero. -/// -/// ``` -/// use std::mem; -/// -/// let x: i32 = unsafe { mem::zeroed() }; -/// assert_eq!(0, x); -/// ``` -/// -/// *Incorrect* usage of this function: initializing a reference with zero. -/// -/// ```no_run -/// use std::mem; -/// -/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn zeroed() -> T { - intrinsics::panic_if_uninhabited::(); - intrinsics::init() -} - -/// Bypasses Rust's normal memory-initialization checks by pretending to -/// produce a value of type `T`, while doing nothing at all. -/// -/// **This functon is deprecated.** Use [`MaybeUninit`] instead. -/// -/// The reason for deprecation is that the function basically cannot be used -/// correctly: [the Rust compiler assumes][inv] that values are properly initialized. -/// As a consequence, calling e.g. `mem::uninitialized::()` causes immediate -/// undefined behavior for returning a `bool` that is not definitely either `true` -/// or `false`. Worse, truly uninitialized memory like what gets returned here -/// is special in that the compiler knows that it does not have a fixed value. -/// This makes it undefined behavior to have uninitialized data in a variable even -/// if that variable has an integer type. -/// (Notice that the rules around uninitialized integers are not finalized yet, but -/// until they are, it is advisable to avoid them.) -/// -/// [`MaybeUninit`]: union.MaybeUninit.html -/// [inv]: union.MaybeUninit.html#initialization-invariant -#[inline] -#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")] -#[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn uninitialized() -> T { - intrinsics::panic_if_uninhabited::(); - intrinsics::uninit() -} - -/// Swaps the values at two mutable locations, without deinitializing either one. -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// let mut x = 5; -/// let mut y = 42; -/// -/// mem::swap(&mut x, &mut y); -/// -/// assert_eq!(42, x); -/// assert_eq!(5, y); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn swap(x: &mut T, y: &mut T) { - unsafe { - ptr::swap_nonoverlapping_one(x, y); - } -} - -/// Moves `src` into the referenced `dest`, returning the previous `dest` value. -/// -/// Neither value is dropped. -/// -/// # Examples -/// -/// A simple example: -/// -/// ``` -/// use std::mem; -/// -/// let mut v: Vec = vec![1, 2]; -/// -/// let old_v = mem::replace(&mut v, vec![3, 4, 5]); -/// assert_eq!(vec![1, 2], old_v); -/// assert_eq!(vec![3, 4, 5], v); -/// ``` -/// -/// `replace` allows consumption of a struct field by replacing it with another value. -/// Without `replace` you can run into issues like these: -/// -/// ```compile_fail,E0507 -/// struct Buffer { buf: Vec } -/// -/// impl Buffer { -/// fn get_and_reset(&mut self) -> Vec { -/// // error: cannot move out of dereference of `&mut`-pointer -/// let buf = self.buf; -/// self.buf = Vec::new(); -/// buf -/// } -/// } -/// ``` -/// -/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset -/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from -/// `self`, allowing it to be returned: -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::mem; -/// -/// # struct Buffer { buf: Vec } -/// impl Buffer { -/// fn get_and_reset(&mut self) -> Vec { -/// mem::replace(&mut self.buf, Vec::new()) -/// } -/// } -/// ``` -/// -/// [`Clone`]: ../../std/clone/trait.Clone.html -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn replace(dest: &mut T, mut src: T) -> T { - swap(dest, &mut src); - src -} - -/// Disposes of a value. -/// -/// This does call the argument's implementation of [`Drop`][drop]. -/// -/// This effectively does nothing for types which implement `Copy`, e.g. -/// integers. Such values are copied and _then_ moved into the function, so the -/// value persists after this function call. -/// -/// This function is not magic; it is literally defined as -/// -/// ``` -/// pub fn drop(_x: T) { } -/// ``` -/// -/// Because `_x` is moved into the function, it is automatically dropped before -/// the function returns. -/// -/// [drop]: ../ops/trait.Drop.html -/// -/// # Examples -/// -/// Basic usage: -/// -/// ``` -/// let v = vec![1, 2, 3]; -/// -/// drop(v); // explicitly drop the vector -/// ``` -/// -/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can -/// release a [`RefCell`] borrow: -/// -/// ``` -/// use std::cell::RefCell; -/// -/// let x = RefCell::new(1); -/// -/// let mut mutable_borrow = x.borrow_mut(); -/// *mutable_borrow = 1; -/// -/// drop(mutable_borrow); // relinquish the mutable borrow on this slot -/// -/// let borrow = x.borrow(); -/// println!("{}", *borrow); -/// ``` -/// -/// Integers and other types implementing [`Copy`] are unaffected by `drop`. -/// -/// ``` -/// #[derive(Copy, Clone)] -/// struct Foo(u8); -/// -/// let x = 1; -/// let y = Foo(2); -/// drop(x); // a copy of `x` is moved and dropped -/// drop(y); // a copy of `y` is moved and dropped -/// -/// println!("x: {}, y: {}", x, y.0); // still available -/// ``` -/// -/// [`RefCell`]: ../../std/cell/struct.RefCell.html -/// [`Copy`]: ../../std/marker/trait.Copy.html -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn drop(_x: T) { } - -/// Interprets `src` as having type `&U`, and then reads `src` without moving -/// the contained value. -/// -/// This function will unsafely assume the pointer `src` is valid for -/// [`size_of::`][size_of] bytes by transmuting `&T` to `&U` and then reading -/// the `&U`. It will also unsafely create a copy of the contained value instead of -/// moving out of `src`. -/// -/// It is not a compile-time error if `T` and `U` have different sizes, but it -/// is highly encouraged to only invoke this function where `T` and `U` have the -/// same size. This function triggers [undefined behavior][ub] if `U` is larger than -/// `T`. -/// -/// [ub]: ../../reference/behavior-considered-undefined.html -/// [size_of]: fn.size_of.html -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// #[repr(packed)] -/// struct Foo { -/// bar: u8, -/// } -/// -/// let foo_slice = [10u8]; -/// -/// unsafe { -/// // Copy the data from 'foo_slice' and treat it as a 'Foo' -/// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice); -/// assert_eq!(foo_struct.bar, 10); -/// -/// // Modify the copied data -/// foo_struct.bar = 20; -/// assert_eq!(foo_struct.bar, 20); -/// } -/// -/// // The contents of 'foo_slice' should not have changed -/// assert_eq!(foo_slice, [10]); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn transmute_copy(src: &T) -> U { - ptr::read_unaligned(src as *const T as *const U) -} - -/// Opaque type representing the discriminant of an enum. -/// -/// See the [`discriminant`] function in this module for more information. -/// -/// [`discriminant`]: fn.discriminant.html -#[stable(feature = "discriminant_value", since = "1.21.0")] -pub struct Discriminant(u64, PhantomData T>); - -// N.B. These trait implementations cannot be derived because we don't want any bounds on T. - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl Copy for Discriminant {} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl clone::Clone for Discriminant { - fn clone(&self) -> Self { - *self - } -} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl cmp::PartialEq for Discriminant { - fn eq(&self, rhs: &Self) -> bool { - self.0 == rhs.0 - } -} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl cmp::Eq for Discriminant {} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl hash::Hash for Discriminant { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl fmt::Debug for Discriminant { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_tuple("Discriminant") - .field(&self.0) - .finish() - } -} - -/// Returns a value uniquely identifying the enum variant in `v`. -/// -/// If `T` is not an enum, calling this function will not result in undefined behavior, but the -/// return value is unspecified. -/// -/// # Stability -/// -/// The discriminant of an enum variant may change if the enum definition changes. A discriminant -/// of some variant will not change between compilations with the same compiler. -/// -/// # Examples -/// -/// This can be used to compare enums that carry data, while disregarding -/// the actual data: -/// -/// ``` -/// use std::mem; -/// -/// enum Foo { A(&'static str), B(i32), C(i32) } -/// -/// assert!(mem::discriminant(&Foo::A("bar")) == mem::discriminant(&Foo::A("baz"))); -/// assert!(mem::discriminant(&Foo::B(1)) == mem::discriminant(&Foo::B(2))); -/// assert!(mem::discriminant(&Foo::B(3)) != mem::discriminant(&Foo::C(3))); -/// ``` -#[stable(feature = "discriminant_value", since = "1.21.0")] -pub fn discriminant(v: &T) -> Discriminant { - unsafe { - Discriminant(intrinsics::discriminant_value(v), PhantomData) - } -} - -/// A wrapper to inhibit compiler from automatically calling `T`’s destructor. -/// -/// This wrapper is 0-cost. -/// -/// `ManuallyDrop` is subject to the same layout optimizations as `T`. -/// As a consequence, it has *no effect* on the assumptions that the compiler makes -/// about all values being initialized at their type. In particular, initializing -/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior. -/// If you need to handle uninitialized data, use [`MaybeUninit`] instead. -/// -/// # Examples -/// -/// This wrapper helps with explicitly documenting the drop order dependencies between fields of -/// the type: -/// -/// ```rust -/// use std::mem::ManuallyDrop; -/// struct Peach; -/// struct Banana; -/// struct Melon; -/// struct FruitBox { -/// // Immediately clear there’s something non-trivial going on with these fields. -/// peach: ManuallyDrop, -/// melon: Melon, // Field that’s independent of the other two. -/// banana: ManuallyDrop, -/// } -/// -/// impl Drop for FruitBox { -/// fn drop(&mut self) { -/// unsafe { -/// // Explicit ordering in which field destructors are run specified in the intuitive -/// // location – the destructor of the structure containing the fields. -/// // Moreover, one can now reorder fields within the struct however much they want. -/// ManuallyDrop::drop(&mut self.peach); -/// ManuallyDrop::drop(&mut self.banana); -/// } -/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets -/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`. -/// } -/// } -/// ``` -/// -/// [`mem::zeroed`]: fn.zeroed.html -/// [`MaybeUninit`]: union.MaybeUninit.html -#[stable(feature = "manually_drop", since = "1.20.0")] -#[lang = "manually_drop"] -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct ManuallyDrop { - value: T, -} - -impl ManuallyDrop { - /// Wrap a value to be manually dropped. - /// - /// # Examples - /// - /// ```rust - /// use std::mem::ManuallyDrop; - /// ManuallyDrop::new(Box::new(())); - /// ``` - #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline(always)] - pub const fn new(value: T) -> ManuallyDrop { - ManuallyDrop { value } - } - - /// Extracts the value from the `ManuallyDrop` container. - /// - /// This allows the value to be dropped again. - /// - /// # Examples - /// - /// ```rust - /// use std::mem::ManuallyDrop; - /// let x = ManuallyDrop::new(Box::new(())); - /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. - /// ``` - #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline(always)] - pub const fn into_inner(slot: ManuallyDrop) -> T { - slot.value - } - - /// Takes the contained value out. - /// - /// This method is primarily intended for moving out values in drop. - /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, - /// you can use this method to take the value and use it however desired. - /// `Drop` will be invoked on the returned value following normal end-of-scope rules. - /// - /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead. - /// - /// # Safety - /// - /// This function semantically moves out the contained value without preventing further usage. - /// It is up to the user of this method to ensure that this container is not used again. - /// - /// [`ManuallyDrop::drop`]: #method.drop - /// [`ManuallyDrop::into_inner`]: #method.into_inner - #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] - #[unstable(feature = "manually_drop_take", issue = "55422")] - #[inline] - pub unsafe fn take(slot: &mut ManuallyDrop) -> T { - ManuallyDrop::into_inner(ptr::read(slot)) - } -} - -impl ManuallyDrop { - /// Manually drops the contained value. - /// - /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. - /// - /// # Safety - /// - /// This function runs the destructor of the contained value and thus the wrapped value - /// now represents uninitialized data. It is up to the user of this method to ensure the - /// uninitialized data is not actually used. - /// - /// [`ManuallyDrop::into_inner`]: #method.into_inner - #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline] - pub unsafe fn drop(slot: &mut ManuallyDrop) { - ptr::drop_in_place(&mut slot.value) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Deref for ManuallyDrop { - type Target = T; - #[inline(always)] - fn deref(&self) -> &T { - &self.value - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl DerefMut for ManuallyDrop { - #[inline(always)] - fn deref_mut(&mut self) -> &mut T { - &mut self.value - } -} - -/// A wrapper type to construct uninitialized instances of `T`. -/// -/// # Initialization invariant -/// -/// The compiler, in general, assumes that variables are properly initialized -/// at their respective type. For example, a variable of reference type must -/// be aligned and non-NULL. This is an invariant that must *always* be upheld, -/// even in unsafe code. As a consequence, zero-initializing a variable of reference -/// type causes instantaneous [undefined behavior][ub], no matter whether that reference -/// ever gets used to access memory: -/// -/// ```rust,no_run -/// use std::mem::{self, MaybeUninit}; -/// -/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! -/// // The equivalent code with `MaybeUninit<&i32>`: -/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! -/// ``` -/// -/// This is exploited by the compiler for various optimizations, such as eliding -/// run-time checks and optimizing `enum` layout. -/// -/// Similarly, entirely uninitialized memory may have any content, while a `bool` must -/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: -/// -/// ```rust,no_run -/// use std::mem::{self, MaybeUninit}; -/// -/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! -/// // The equivalent code with `MaybeUninit`: -/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! -/// ``` -/// -/// Moreover, uninitialized memory is special in that the compiler knows that -/// it does not have a fixed value. This makes it undefined behavior to have -/// uninitialized data in a variable even if that variable has an integer type, -/// which otherwise can hold any *fixed* bit pattern: -/// -/// ```rust,no_run -/// use std::mem::{self, MaybeUninit}; -/// -/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! -/// // The equivalent code with `MaybeUninit`: -/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! -/// ``` -/// (Notice that the rules around uninitialized integers are not finalized yet, but -/// until they are, it is advisable to avoid them.) -/// -/// On top of that, remember that most types have additional invariants beyond merely -/// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] -/// is considered initialized because the only requirement the compiler knows about it -/// is that the data pointer must be non-null. Creating such a `Vec` does not cause -/// *immediate* undefined behavior, but will cause undefined behavior with most -/// safe operations (including dropping it). -/// -/// [`Vec`]: ../../std/vec/struct.Vec.html -/// -/// # Examples -/// -/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data. -/// It is a signal to the compiler indicating that the data here might *not* -/// be initialized: -/// -/// ```rust -/// use std::mem::MaybeUninit; -/// -/// // Create an explicitly uninitialized reference. The compiler knows that data inside -/// // a `MaybeUninit` may be invalid, and hence this is not UB: -/// let mut x = MaybeUninit::<&i32>::uninit(); -/// // Set it to a valid value. -/// unsafe { x.as_mut_ptr().write(&0); } -/// // Extract the initialized data -- this is only allowed *after* properly -/// // initializing `x`! -/// let x = unsafe { x.assume_init() }; -/// ``` -/// -/// The compiler then knows to not make any incorrect assumptions or optimizations on this code. -/// -/// ## out-pointers -/// -/// You can use `MaybeUninit` to implement "out-pointers": instead of returning data -/// from a function, pass it a pointer to some (uninitialized) memory to put the -/// result into. This can be useful when it is important for the caller to control -/// how the memory the result is stored in gets allocated, and you want to avoid -/// unnecessary moves. -/// -/// ``` -/// use std::mem::MaybeUninit; -/// -/// unsafe fn make_vec(out: *mut Vec) { -/// // `write` does not drop the old contents, which is important. -/// out.write(vec![1, 2, 3]); -/// } -/// -/// let mut v: MaybeUninit> = MaybeUninit::uninit(); -/// unsafe { make_vec(v.as_mut_ptr()); } -/// // Now we know `v` is initialized! This also makes sure the vector gets -/// // properly dropped. -/// let v = unsafe { v.assume_init() }; -/// assert_eq!(&v, &[1, 2, 3]); -/// ``` -/// -/// ## Initializing an array element-by-element -/// -/// `MaybeUninit` can be used to initialize a large array element-by-element: -/// -/// ``` -/// use std::mem::{self, MaybeUninit}; -/// use std::ptr; -/// -/// let data = { -/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is -/// // safe because the type we are claiming to have initialized here is a -/// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit>; 1000] = unsafe { -/// MaybeUninit::uninit().assume_init() -/// }; -/// -/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, -/// // we have a memory leak, but there is no memory safety issue. -/// for elem in &mut data[..] { -/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); } -/// } -/// -/// // Everything is initialized. Transmute the array to the -/// // initialized type. -/// unsafe { mem::transmute::<_, [Vec; 1000]>(data) } -/// }; -/// -/// assert_eq!(&data[0], &[42]); -/// ``` -/// -/// You can also work with partially initialized arrays, which could -/// be found in low-level datastructures. -/// -/// ``` -/// use std::mem::MaybeUninit; -/// use std::ptr; -/// -/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is -/// // safe because the type we are claiming to have initialized here is a -/// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; -/// // Count the number of elements we have assigned. -/// let mut data_len: usize = 0; -/// -/// for elem in &mut data[0..500] { -/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); } -/// data_len += 1; -/// } -/// -/// // For each item in the array, drop if we allocated it. -/// for elem in &mut data[0..data_len] { -/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); } -/// } -/// ``` -/// -/// ## Initializing a struct field-by-field -/// -/// There is currently no supported way to create a raw pointer or reference -/// to a field of a struct inside `MaybeUninit`. That means it is not possible -/// to create a struct by calling `MaybeUninit::uninit::()` and then writing -/// to its fields. -/// -/// [ub]: ../../reference/behavior-considered-undefined.html -/// -/// # Layout -/// -/// `MaybeUninit` is guaranteed to have the same size and alignment as `T`: -/// -/// ```rust -/// use std::mem::{MaybeUninit, size_of, align_of}; -/// assert_eq!(size_of::>(), size_of::()); -/// assert_eq!(align_of::>(), align_of::()); -/// ``` -/// -/// However remember that a type *containing* a `MaybeUninit` is not necessarily the same -/// layout; Rust does not in general guarantee that the fields of a `Foo` have the same order as -/// a `Foo` even if `T` and `U` have the same size and alignment. Furthermore because any bit -/// value is valid for a `MaybeUninit` the compiler can't apply non-zero/niche-filling -/// optimizations, potentially resulting in a larger size: -/// -/// ```rust -/// # use std::mem::{MaybeUninit, size_of}; -/// assert_eq!(size_of::>(), 1); -/// assert_eq!(size_of::>>(), 2); -/// ``` -#[allow(missing_debug_implementations)] -#[stable(feature = "maybe_uninit", since = "1.36.0")] -#[derive(Copy)] -pub union MaybeUninit { - uninit: (), - value: ManuallyDrop, -} - -#[stable(feature = "maybe_uninit", since = "1.36.0")] -impl Clone for MaybeUninit { - #[inline(always)] - fn clone(&self) -> Self { - // Not calling `T::clone()`, we cannot know if we are initialized enough for that. - *self - } -} - -impl MaybeUninit { - /// Creates a new `MaybeUninit` initialized with the given value. - /// It is safe to call [`assume_init`] on the return value of this function. - /// - /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// [`assume_init`]: #method.assume_init - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub const fn new(val: T) -> MaybeUninit { - MaybeUninit { value: ManuallyDrop::new(val) } - } - - /// Creates a new `MaybeUninit` in an uninitialized state. - /// - /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// See the [type-level documentation][type] for some examples. - /// - /// [type]: union.MaybeUninit.html - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub const fn uninit() -> MaybeUninit { - MaybeUninit { uninit: () } - } - - /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being - /// filled with `0` bytes. It depends on `T` whether that already makes for - /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, - /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not - /// be null. - /// - /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// # Example - /// - /// Correct usage of this function: initializing a struct with zero, where all - /// fields of the struct can hold the bit-pattern 0 as a valid value. - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::<(u8, bool)>::zeroed(); - /// let x = unsafe { x.assume_init() }; - /// assert_eq!(x, (0, false)); - /// ``` - /// - /// *Incorrect* usage of this function: initializing a struct with zero, where some fields - /// cannot hold 0 as a valid value. - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// enum NotZero { One = 1, Two = 2 }; - /// - /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); - /// let x = unsafe { x.assume_init() }; - /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. - /// // This is undefined behavior. - /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline] - pub fn zeroed() -> MaybeUninit { - let mut u = MaybeUninit::::uninit(); - unsafe { - u.as_mut_ptr().write_bytes(0u8, 1); - } - u - } - - /// Sets the value of the `MaybeUninit`. This overwrites any previous value - /// without dropping it, so be careful not to use this twice unless you want to - /// skip running the destructor. For your convenience, this also returns a mutable - /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] - #[inline(always)] - pub fn write(&mut self, val: T) -> &mut T { - unsafe { - self.value = ManuallyDrop::new(val); - self.get_mut() - } - } - - /// Gets a pointer to the contained value. Reading from this pointer or turning it - /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. - /// Writing to memory that this pointer (non-transitively) points to is undefined behavior - /// (except inside an `UnsafeCell`). - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } - /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. - /// let x_vec = unsafe { &*x.as_ptr() }; - /// assert_eq!(x_vec.len(), 3); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::>::uninit(); - /// let x_vec = unsafe { &*x.as_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. - /// ``` - /// - /// (Notice that the rules around references to uninitialized data are not finalized yet, but - /// until they are, it is advisable to avoid them.) - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub fn as_ptr(&self) -> *const T { - unsafe { &*self.value as *const T } - } - - /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it - /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } - /// // Create a reference into the `MaybeUninit>`. - /// // This is okay because we initialized it. - /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; - /// x_vec.push(3); - /// assert_eq!(x_vec.len(), 4); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::>::uninit(); - /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. - /// ``` - /// - /// (Notice that the rules around references to uninitialized data are not finalized yet, but - /// until they are, it is advisable to avoid them.) - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub fn as_mut_ptr(&mut self) -> *mut T { - unsafe { &mut *self.value as *mut T } - } - - /// Extracts the value from the `MaybeUninit` container. This is a great way - /// to ensure that the data will get dropped, because the resulting `T` is - /// subject to the usual drop handling. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes immediate undefined - /// behavior. The [type-level documentation][inv] contains more information about - /// this initialization invariant. - /// - /// [inv]: #initialization-invariant - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::::uninit(); - /// unsafe { x.as_mut_ptr().write(true); } - /// let x_init = unsafe { x.assume_init() }; - /// assert_eq!(x_init, true); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::>::uninit(); - /// let x_init = unsafe { x.assume_init() }; - /// // `x` had not been initialized yet, so this last line caused undefined behavior. - /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub unsafe fn assume_init(self) -> T { - intrinsics::panic_if_uninhabited::(); - ManuallyDrop::into_inner(self.value) - } - - /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject - /// to the usual drop handling. - /// - /// Whenever possible, it is preferrable to use [`assume_init`] instead, which - /// prevents duplicating the content of the `MaybeUninit`. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. The [type-level documentation][inv] contains more information about - /// this initialization invariant. - /// - /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit`. When using - /// multiple copies of the data (by calling `read` multiple times, or first - /// calling `read` and then [`assume_init`]), it is your responsibility - /// to ensure that that data may indeed be duplicated. - /// - /// [inv]: #initialization-invariant - /// [`assume_init`]: #method.assume_init - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// #![feature(maybe_uninit_extra)] - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::::uninit(); - /// x.write(13); - /// let x1 = unsafe { x.read() }; - /// // `u32` is `Copy`, so we may read multiple times. - /// let x2 = unsafe { x.read() }; - /// assert_eq!(x1, x2); - /// - /// let mut x = MaybeUninit::>>::uninit(); - /// x.write(None); - /// let x1 = unsafe { x.read() }; - /// // Duplicating a `None` value is okay, so we may read multiple times. - /// let x2 = unsafe { x.read() }; - /// assert_eq!(x1, x2); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// #![feature(maybe_uninit_extra)] - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::>>::uninit(); - /// x.write(Some(vec![0,1,2])); - /// let x1 = unsafe { x.read() }; - /// let x2 = unsafe { x.read() }; - /// // We now created two copies of the same vector, leading to a double-free when - /// // they both get dropped! - /// ``` - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] - #[inline(always)] - pub unsafe fn read(&self) -> T { - intrinsics::panic_if_uninhabited::(); - self.as_ptr().read() - } - - /// Gets a reference to the contained value. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] - #[inline(always)] - pub unsafe fn get_ref(&self) -> &T { - &*self.value - } - - /// Gets a mutable reference to the contained value. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. - // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references - // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make - // a final decision about the rules before stabilization. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] - #[inline(always)] - pub unsafe fn get_mut(&mut self) -> &mut T { - &mut *self.value - } - - /// Gets a pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] - #[inline(always)] - pub fn first_ptr(this: &[MaybeUninit]) -> *const T { - this as *const [MaybeUninit] as *const T - } - - /// Gets a mutable pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] - #[inline(always)] - pub fn first_ptr_mut(this: &mut [MaybeUninit]) -> *mut T { - this as *mut [MaybeUninit] as *mut T - } -} diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs new file mode 100644 index 0000000000..3ad1223e33 --- /dev/null +++ b/src/libcore/mem/manually_drop.rs @@ -0,0 +1,146 @@ +use crate::ptr; +use crate::ops::{Deref, DerefMut}; + +/// A wrapper to inhibit compiler from automatically calling `T`’s destructor. +/// +/// This wrapper is 0-cost. +/// +/// `ManuallyDrop` is subject to the same layout optimizations as `T`. +/// As a consequence, it has *no effect* on the assumptions that the compiler makes +/// about all values being initialized at their type. In particular, initializing +/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior. +/// If you need to handle uninitialized data, use [`MaybeUninit`] instead. +/// +/// # Examples +/// +/// This wrapper helps with explicitly documenting the drop order dependencies between fields of +/// the type: +/// +/// ```rust +/// use std::mem::ManuallyDrop; +/// struct Peach; +/// struct Banana; +/// struct Melon; +/// struct FruitBox { +/// // Immediately clear there’s something non-trivial going on with these fields. +/// peach: ManuallyDrop, +/// melon: Melon, // Field that’s independent of the other two. +/// banana: ManuallyDrop, +/// } +/// +/// impl Drop for FruitBox { +/// fn drop(&mut self) { +/// unsafe { +/// // Explicit ordering in which field destructors are run specified in the intuitive +/// // location – the destructor of the structure containing the fields. +/// // Moreover, one can now reorder fields within the struct however much they want. +/// ManuallyDrop::drop(&mut self.peach); +/// ManuallyDrop::drop(&mut self.banana); +/// } +/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets +/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`. +/// } +/// } +/// ``` +/// +/// [`mem::zeroed`]: fn.zeroed.html +/// [`MaybeUninit`]: union.MaybeUninit.html +#[stable(feature = "manually_drop", since = "1.20.0")] +#[lang = "manually_drop"] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct ManuallyDrop { + value: T, +} + +impl ManuallyDrop { + /// Wrap a value to be manually dropped. + /// + /// # Examples + /// + /// ```rust + /// use std::mem::ManuallyDrop; + /// ManuallyDrop::new(Box::new(())); + /// ``` + #[stable(feature = "manually_drop", since = "1.20.0")] + #[inline(always)] + pub const fn new(value: T) -> ManuallyDrop { + ManuallyDrop { value } + } + + /// Extracts the value from the `ManuallyDrop` container. + /// + /// This allows the value to be dropped again. + /// + /// # Examples + /// + /// ```rust + /// use std::mem::ManuallyDrop; + /// let x = ManuallyDrop::new(Box::new(())); + /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. + /// ``` + #[stable(feature = "manually_drop", since = "1.20.0")] + #[inline(always)] + pub const fn into_inner(slot: ManuallyDrop) -> T { + slot.value + } + + /// Takes the contained value out. + /// + /// This method is primarily intended for moving out values in drop. + /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, + /// you can use this method to take the value and use it however desired. + /// `Drop` will be invoked on the returned value following normal end-of-scope rules. + /// + /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead. + /// + /// # Safety + /// + /// This function semantically moves out the contained value without preventing further usage. + /// It is up to the user of this method to ensure that this container is not used again. + /// + /// [`ManuallyDrop::drop`]: #method.drop + /// [`ManuallyDrop::into_inner`]: #method.into_inner + #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] + #[unstable(feature = "manually_drop_take", issue = "55422")] + #[inline] + pub unsafe fn take(slot: &mut ManuallyDrop) -> T { + ManuallyDrop::into_inner(ptr::read(slot)) + } +} + +impl ManuallyDrop { + /// Manually drops the contained value. + /// + /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. + /// + /// # Safety + /// + /// This function runs the destructor of the contained value and thus the wrapped value + /// now represents uninitialized data. It is up to the user of this method to ensure the + /// uninitialized data is not actually used. + /// + /// [`ManuallyDrop::into_inner`]: #method.into_inner + #[stable(feature = "manually_drop", since = "1.20.0")] + #[inline] + pub unsafe fn drop(slot: &mut ManuallyDrop) { + ptr::drop_in_place(&mut slot.value) + } +} + +#[stable(feature = "manually_drop", since = "1.20.0")] +impl Deref for ManuallyDrop { + type Target = T; + #[inline(always)] + fn deref(&self) -> &T { + &self.value + } +} + +#[stable(feature = "manually_drop", since = "1.20.0")] +impl DerefMut for ManuallyDrop { + #[inline(always)] + fn deref_mut(&mut self) -> &mut T { + &mut self.value + } +} diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs new file mode 100644 index 0000000000..28e1e22ba7 --- /dev/null +++ b/src/libcore/mem/maybe_uninit.rs @@ -0,0 +1,533 @@ +use crate::intrinsics; +use crate::mem::ManuallyDrop; + +/// A wrapper type to construct uninitialized instances of `T`. +/// +/// # Initialization invariant +/// +/// The compiler, in general, assumes that variables are properly initialized +/// at their respective type. For example, a variable of reference type must +/// be aligned and non-NULL. This is an invariant that must *always* be upheld, +/// even in unsafe code. As a consequence, zero-initializing a variable of reference +/// type causes instantaneous [undefined behavior][ub], no matter whether that reference +/// ever gets used to access memory: +/// +/// ```rust,no_run +/// use std::mem::{self, MaybeUninit}; +/// +/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! +/// // The equivalent code with `MaybeUninit<&i32>`: +/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! +/// ``` +/// +/// This is exploited by the compiler for various optimizations, such as eliding +/// run-time checks and optimizing `enum` layout. +/// +/// Similarly, entirely uninitialized memory may have any content, while a `bool` must +/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: +/// +/// ```rust,no_run +/// use std::mem::{self, MaybeUninit}; +/// +/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! +/// // The equivalent code with `MaybeUninit`: +/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! +/// ``` +/// +/// Moreover, uninitialized memory is special in that the compiler knows that +/// it does not have a fixed value. This makes it undefined behavior to have +/// uninitialized data in a variable even if that variable has an integer type, +/// which otherwise can hold any *fixed* bit pattern: +/// +/// ```rust,no_run +/// use std::mem::{self, MaybeUninit}; +/// +/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! +/// // The equivalent code with `MaybeUninit`: +/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! +/// ``` +/// (Notice that the rules around uninitialized integers are not finalized yet, but +/// until they are, it is advisable to avoid them.) +/// +/// On top of that, remember that most types have additional invariants beyond merely +/// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] +/// is considered initialized because the only requirement the compiler knows about it +/// is that the data pointer must be non-null. Creating such a `Vec` does not cause +/// *immediate* undefined behavior, but will cause undefined behavior with most +/// safe operations (including dropping it). +/// +/// [`Vec`]: ../../std/vec/struct.Vec.html +/// +/// # Examples +/// +/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data. +/// It is a signal to the compiler indicating that the data here might *not* +/// be initialized: +/// +/// ```rust +/// use std::mem::MaybeUninit; +/// +/// // Create an explicitly uninitialized reference. The compiler knows that data inside +/// // a `MaybeUninit` may be invalid, and hence this is not UB: +/// let mut x = MaybeUninit::<&i32>::uninit(); +/// // Set it to a valid value. +/// unsafe { x.as_mut_ptr().write(&0); } +/// // Extract the initialized data -- this is only allowed *after* properly +/// // initializing `x`! +/// let x = unsafe { x.assume_init() }; +/// ``` +/// +/// The compiler then knows to not make any incorrect assumptions or optimizations on this code. +/// +/// You can think of `MaybeUninit` as being a bit like `Option` but without +/// any of the run-time tracking and without any of the safety checks. +/// +/// ## out-pointers +/// +/// You can use `MaybeUninit` to implement "out-pointers": instead of returning data +/// from a function, pass it a pointer to some (uninitialized) memory to put the +/// result into. This can be useful when it is important for the caller to control +/// how the memory the result is stored in gets allocated, and you want to avoid +/// unnecessary moves. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// +/// unsafe fn make_vec(out: *mut Vec) { +/// // `write` does not drop the old contents, which is important. +/// out.write(vec![1, 2, 3]); +/// } +/// +/// let mut v = MaybeUninit::uninit(); +/// unsafe { make_vec(v.as_mut_ptr()); } +/// // Now we know `v` is initialized! This also makes sure the vector gets +/// // properly dropped. +/// let v = unsafe { v.assume_init() }; +/// assert_eq!(&v, &[1, 2, 3]); +/// ``` +/// +/// ## Initializing an array element-by-element +/// +/// `MaybeUninit` can be used to initialize a large array element-by-element: +/// +/// ``` +/// use std::mem::{self, MaybeUninit}; +/// use std::ptr; +/// +/// let data = { +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit>; 1000] = unsafe { +/// MaybeUninit::uninit().assume_init() +/// }; +/// +/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, +/// // we have a memory leak, but there is no memory safety issue. +/// for elem in &mut data[..] { +/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); } +/// } +/// +/// // Everything is initialized. Transmute the array to the +/// // initialized type. +/// unsafe { mem::transmute::<_, [Vec; 1000]>(data) } +/// }; +/// +/// assert_eq!(&data[0], &[42]); +/// ``` +/// +/// You can also work with partially initialized arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// use std::ptr; +/// +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// +/// for elem in &mut data[0..500] { +/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); } +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for elem in &mut data[0..data_len] { +/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); } +/// } +/// ``` +/// +/// ## Initializing a struct field-by-field +/// +/// There is currently no supported way to create a raw pointer or reference +/// to a field of a struct inside `MaybeUninit`. That means it is not possible +/// to create a struct by calling `MaybeUninit::uninit::()` and then writing +/// to its fields. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Layout +/// +/// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as `T`: +/// +/// ```rust +/// use std::mem::{MaybeUninit, size_of, align_of}; +/// assert_eq!(size_of::>(), size_of::()); +/// assert_eq!(align_of::>(), align_of::()); +/// ``` +/// +/// However remember that a type *containing* a `MaybeUninit` is not necessarily the same +/// layout; Rust does not in general guarantee that the fields of a `Foo` have the same order as +/// a `Foo` even if `T` and `U` have the same size and alignment. Furthermore because any bit +/// value is valid for a `MaybeUninit` the compiler can't apply non-zero/niche-filling +/// optimizations, potentially resulting in a larger size: +/// +/// ```rust +/// # use std::mem::{MaybeUninit, size_of}; +/// assert_eq!(size_of::>(), 1); +/// assert_eq!(size_of::>>(), 2); +/// ``` +/// +/// If `T` is FFI-safe, then so is `MaybeUninit`. +/// +/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, +/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option` and +/// `Option>` may still have different sizes, and types containing a field of type +/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit`. +/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the +/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact +/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not +/// remain `#[repr(transparent)]`. That said, `MaybeUninit` will *always* guarantee that it has +/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that +/// guarantee may evolve. +#[allow(missing_debug_implementations)] +#[stable(feature = "maybe_uninit", since = "1.36.0")] +#[derive(Copy)] +#[cfg_attr(not(bootstrap), repr(transparent))] +pub union MaybeUninit { + uninit: (), + value: ManuallyDrop, +} + +#[stable(feature = "maybe_uninit", since = "1.36.0")] +impl Clone for MaybeUninit { + #[inline(always)] + fn clone(&self) -> Self { + // Not calling `T::clone()`, we cannot know if we are initialized enough for that. + *self + } +} + +impl MaybeUninit { + /// Creates a new `MaybeUninit` initialized with the given value. + /// It is safe to call [`assume_init`] on the return value of this function. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// [`assume_init`]: #method.assume_init + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[inline(always)] + pub const fn new(val: T) -> MaybeUninit { + MaybeUninit { value: ManuallyDrop::new(val) } + } + + /// Creates a new `MaybeUninit` in an uninitialized state. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// See the [type-level documentation][type] for some examples. + /// + /// [type]: union.MaybeUninit.html + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[inline(always)] + pub const fn uninit() -> MaybeUninit { + MaybeUninit { uninit: () } + } + + /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being + /// filled with `0` bytes. It depends on `T` whether that already makes for + /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, + /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not + /// be null. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// # Example + /// + /// Correct usage of this function: initializing a struct with zero, where all + /// fields of the struct can hold the bit-pattern 0 as a valid value. + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::<(u8, bool)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// assert_eq!(x, (0, false)); + /// ``` + /// + /// *Incorrect* usage of this function: initializing a struct with zero, where some fields + /// cannot hold 0 as a valid value. + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// enum NotZero { One = 1, Two = 2 }; + /// + /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. + /// // This is undefined behavior. + /// ``` + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[inline] + pub fn zeroed() -> MaybeUninit { + let mut u = MaybeUninit::::uninit(); + unsafe { + u.as_mut_ptr().write_bytes(0u8, 1); + } + u + } + + /// Sets the value of the `MaybeUninit`. This overwrites any previous value + /// without dropping it, so be careful not to use this twice unless you want to + /// skip running the destructor. For your convenience, this also returns a mutable + /// reference to the (now safely initialized) contents of `self`. + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[inline(always)] + pub fn write(&mut self, val: T) -> &mut T { + unsafe { + self.value = ManuallyDrop::new(val); + self.get_mut() + } + } + + /// Gets a pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// Writing to memory that this pointer (non-transitively) points to is undefined behavior + /// (except inside an `UnsafeCell`). + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } + /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. + /// let x_vec = unsafe { &*x.as_ptr() }; + /// assert_eq!(x_vec.len(), 3); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &*x.as_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// ``` + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[inline(always)] + pub fn as_ptr(&self) -> *const T { + unsafe { &*self.value as *const T } + } + + /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } + /// // Create a reference into the `MaybeUninit>`. + /// // This is okay because we initialized it. + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// x_vec.push(3); + /// assert_eq!(x_vec.len(), 4); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// ``` + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[inline(always)] + pub fn as_mut_ptr(&mut self) -> *mut T { + unsafe { &mut *self.value as *mut T } + } + + /// Extracts the value from the `MaybeUninit` container. This is a great way + /// to ensure that the data will get dropped, because the resulting `T` is + /// subject to the usual drop handling. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes immediate undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// [inv]: #initialization-invariant + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// unsafe { x.as_mut_ptr().write(true); } + /// let x_init = unsafe { x.assume_init() }; + /// assert_eq!(x_init, true); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_init = unsafe { x.assume_init() }; + /// // `x` had not been initialized yet, so this last line caused undefined behavior. + /// ``` + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[inline(always)] + pub unsafe fn assume_init(self) -> T { + intrinsics::panic_if_uninhabited::(); + ManuallyDrop::into_inner(self.value) + } + + /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject + /// to the usual drop handling. + /// + /// Whenever possible, it is preferrable to use [`assume_init`] instead, which + /// prevents duplicating the content of the `MaybeUninit`. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit`. When using + /// multiple copies of the data (by calling `read` multiple times, or first + /// calling `read` and then [`assume_init`]), it is your responsibility + /// to ensure that that data may indeed be duplicated. + /// + /// [inv]: #initialization-invariant + /// [`assume_init`]: #method.assume_init + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// #![feature(maybe_uninit_extra)] + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// x.write(13); + /// let x1 = unsafe { x.read() }; + /// // `u32` is `Copy`, so we may read multiple times. + /// let x2 = unsafe { x.read() }; + /// assert_eq!(x1, x2); + /// + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(None); + /// let x1 = unsafe { x.read() }; + /// // Duplicating a `None` value is okay, so we may read multiple times. + /// let x2 = unsafe { x.read() }; + /// assert_eq!(x1, x2); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// #![feature(maybe_uninit_extra)] + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(Some(vec![0,1,2])); + /// let x1 = unsafe { x.read() }; + /// let x2 = unsafe { x.read() }; + /// // We now created two copies of the same vector, leading to a double-free when + /// // they both get dropped! + /// ``` + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[inline(always)] + pub unsafe fn read(&self) -> T { + intrinsics::panic_if_uninhabited::(); + self.as_ptr().read() + } + + /// Gets a reference to the contained value. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes undefined + /// behavior. + #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[inline(always)] + pub unsafe fn get_ref(&self) -> &T { + &*self.value + } + + /// Gets a mutable reference to the contained value. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes undefined + /// behavior. + // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references + // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make + // a final decision about the rules before stabilization. + #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[inline(always)] + pub unsafe fn get_mut(&mut self) -> &mut T { + &mut *self.value + } + + /// Gets a pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[inline(always)] + pub fn first_ptr(this: &[MaybeUninit]) -> *const T { + this as *const [MaybeUninit] as *const T + } + + /// Gets a mutable pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[inline(always)] + pub fn first_ptr_mut(this: &mut [MaybeUninit]) -> *mut T { + this as *mut [MaybeUninit] as *mut T + } +} diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs new file mode 100644 index 0000000000..e110e93a95 --- /dev/null +++ b/src/libcore/mem/mod.rs @@ -0,0 +1,810 @@ +//! Basic functions for dealing with memory. +//! +//! This module contains functions for querying the size and alignment of +//! types, initializing and manipulating memory. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::clone; +use crate::cmp; +use crate::fmt; +use crate::hash; +use crate::intrinsics; +use crate::marker::{Copy, PhantomData, Sized}; +use crate::ptr; + +mod manually_drop; +#[stable(feature = "manually_drop", since = "1.20.0")] +pub use manually_drop::ManuallyDrop; + +mod maybe_uninit; +#[stable(feature = "maybe_uninit", since = "1.36.0")] +pub use maybe_uninit::MaybeUninit; + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] +pub use crate::intrinsics::transmute; + +/// Takes ownership and "forgets" about the value **without running its destructor**. +/// +/// Any resources the value manages, such as heap memory or a file handle, will linger +/// forever in an unreachable state. However, it does not guarantee that pointers +/// to this memory will remain valid. +/// +/// * If you want to leak memory, see [`Box::leak`][leak]. +/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw]. +/// * If you want to dispose of a value properly, running its destructor, see +/// [`mem::drop`][drop]. +/// +/// # Safety +/// +/// `forget` is not marked as `unsafe`, because Rust's safety guarantees +/// do not include a guarantee that destructors will always run. For example, +/// a program can create a reference cycle using [`Rc`][rc], or call +/// [`process::exit`][exit] to exit without running destructors. Thus, allowing +/// `mem::forget` from safe code does not fundamentally change Rust's safety +/// guarantees. +/// +/// That said, leaking resources such as memory or I/O objects is usually undesirable, +/// so `forget` is only recommended for specialized use cases like those shown below. +/// +/// Because forgetting a value is allowed, any `unsafe` code you write must +/// allow for this possibility. You cannot return a value and expect that the +/// caller will necessarily run the value's destructor. +/// +/// [rc]: ../../std/rc/struct.Rc.html +/// [exit]: ../../std/process/fn.exit.html +/// +/// # Examples +/// +/// Leak an I/O object, never closing the file: +/// +/// ```no_run +/// use std::mem; +/// use std::fs::File; +/// +/// let file = File::open("foo.txt").unwrap(); +/// mem::forget(file); +/// ``` +/// +/// The practical use cases for `forget` are rather specialized and mainly come +/// up in unsafe or FFI code. +/// +/// [drop]: fn.drop.html +/// [uninit]: fn.uninitialized.html +/// [clone]: ../clone/trait.Clone.html +/// [swap]: fn.swap.html +/// [box]: ../../std/boxed/struct.Box.html +/// [leak]: ../../std/boxed/struct.Box.html#method.leak +/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw +/// [ub]: ../../reference/behavior-considered-undefined.html +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn forget(t: T) { + ManuallyDrop::new(t); +} + +/// Like [`forget`], but also accepts unsized values. +/// +/// This function is just a shim intended to be removed when the `unsized_locals` feature gets +/// stabilized. +/// +/// [`forget`]: fn.forget.html +#[inline] +#[unstable(feature = "forget_unsized", issue = "0")] +pub fn forget_unsized(t: T) { + unsafe { intrinsics::forget(t) } +} + +/// Returns the size of a type in bytes. +/// +/// More specifically, this is the offset in bytes between successive elements +/// in an array with that item type including alignment padding. Thus, for any +/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::()`. +/// +/// In general, the size of a type is not stable across compilations, but +/// specific types such as primitives are. +/// +/// The following table gives the size for primitives. +/// +/// Type | size_of::\() +/// ---- | --------------- +/// () | 0 +/// bool | 1 +/// u8 | 1 +/// u16 | 2 +/// u32 | 4 +/// u64 | 8 +/// u128 | 16 +/// i8 | 1 +/// i16 | 2 +/// i32 | 4 +/// i64 | 8 +/// i128 | 16 +/// f32 | 4 +/// f64 | 8 +/// char | 4 +/// +/// Furthermore, `usize` and `isize` have the same size. +/// +/// The types `*const T`, `&T`, `Box`, `Option<&T>`, and `Option>` all have +/// the same size. If `T` is Sized, all of those types have the same size as `usize`. +/// +/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` +/// have the same size. Likewise for `*const T` and `*mut T`. +/// +/// # Size of `#[repr(C)]` items +/// +/// The `C` representation for items has a defined layout. With this layout, +/// the size of items is also stable as long as all fields have a stable size. +/// +/// ## Size of Structs +/// +/// For `structs`, the size is determined by the following algorithm. +/// +/// For each field in the struct ordered by declaration order: +/// +/// 1. Add the size of the field. +/// 2. Round up the current size to the nearest multiple of the next field's [alignment]. +/// +/// Finally, round the size of the struct to the nearest multiple of its [alignment]. +/// The alignment of the struct is usually the largest alignment of all its +/// fields; this can be changed with the use of `repr(align(N))`. +/// +/// Unlike `C`, zero sized structs are not rounded up to one byte in size. +/// +/// ## Size of Enums +/// +/// Enums that carry no data other than the discriminant have the same size as C enums +/// on the platform they are compiled for. +/// +/// ## Size of Unions +/// +/// The size of a union is the size of its largest field. +/// +/// Unlike `C`, zero sized unions are not rounded up to one byte in size. +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// // Some primitives +/// assert_eq!(4, mem::size_of::()); +/// assert_eq!(8, mem::size_of::()); +/// assert_eq!(0, mem::size_of::<()>()); +/// +/// // Some arrays +/// assert_eq!(8, mem::size_of::<[i32; 2]>()); +/// assert_eq!(12, mem::size_of::<[i32; 3]>()); +/// assert_eq!(0, mem::size_of::<[i32; 0]>()); +/// +/// +/// // Pointer size equality +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); +/// assert_eq!(mem::size_of::>(), mem::size_of::>>()); +/// ``` +/// +/// Using `#[repr(C)]`. +/// +/// ``` +/// use std::mem; +/// +/// #[repr(C)] +/// struct FieldStruct { +/// first: u8, +/// second: u16, +/// third: u8 +/// } +/// +/// // The size of the first field is 1, so add 1 to the size. Size is 1. +/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2. +/// // The size of the second field is 2, so add 2 to the size. Size is 4. +/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4. +/// // The size of the third field is 1, so add 1 to the size. Size is 5. +/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its +/// // fields is 2), so add 1 to the size for padding. Size is 6. +/// assert_eq!(6, mem::size_of::()); +/// +/// #[repr(C)] +/// struct TupleStruct(u8, u16, u8); +/// +/// // Tuple structs follow the same rules. +/// assert_eq!(6, mem::size_of::()); +/// +/// // Note that reordering the fields can lower the size. We can remove both padding bytes +/// // by putting `third` before `second`. +/// #[repr(C)] +/// struct FieldStructOptimized { +/// first: u8, +/// third: u8, +/// second: u16 +/// } +/// +/// assert_eq!(4, mem::size_of::()); +/// +/// // Union size is the size of the largest field. +/// #[repr(C)] +/// union ExampleUnion { +/// smaller: u8, +/// larger: u16 +/// } +/// +/// assert_eq!(2, mem::size_of::()); +/// ``` +/// +/// [alignment]: ./fn.align_of.html +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_promotable] +pub const fn size_of() -> usize { + intrinsics::size_of::() +} + +/// Returns the size of the pointed-to value in bytes. +/// +/// This is usually the same as `size_of::()`. However, when `T` *has* no +/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], +/// then `size_of_val` can be used to get the dynamically-known size. +/// +/// [slice]: ../../std/primitive.slice.html +/// [trait object]: ../../book/ch17-02-trait-objects.html +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// assert_eq!(4, mem::size_of_val(&5i32)); +/// +/// let x: [u8; 13] = [0; 13]; +/// let y: &[u8] = &x; +/// assert_eq!(13, mem::size_of_val(y)); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn size_of_val(val: &T) -> usize { + unsafe { intrinsics::size_of_val(val) } +} + +/// Returns the [ABI]-required minimum alignment of a type. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// # #![allow(deprecated)] +/// use std::mem; +/// +/// assert_eq!(4, mem::min_align_of::()); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] +pub fn min_align_of() -> usize { + intrinsics::min_align_of::() +} + +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// # #![allow(deprecated)] +/// use std::mem; +/// +/// assert_eq!(4, mem::min_align_of_val(&5i32)); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")] +pub fn min_align_of_val(val: &T) -> usize { + unsafe { intrinsics::min_align_of_val(val) } +} + +/// Returns the [ABI]-required minimum alignment of a type. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// assert_eq!(4, mem::align_of::()); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_promotable] +pub const fn align_of() -> usize { + intrinsics::min_align_of::() +} + +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// assert_eq!(4, mem::align_of_val(&5i32)); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn align_of_val(val: &T) -> usize { + unsafe { intrinsics::min_align_of_val(val) } +} + +/// Returns `true` if dropping values of type `T` matters. +/// +/// This is purely an optimization hint, and may be implemented conservatively: +/// it may return `true` for types that don't actually need to be dropped. +/// As such always returning `true` would be a valid implementation of +/// this function. However if this function actually returns `false`, then you +/// can be certain dropping `T` has no side effect. +/// +/// Low level implementations of things like collections, which need to manually +/// drop their data, should use this function to avoid unnecessarily +/// trying to drop all their contents when they are destroyed. This might not +/// make a difference in release builds (where a loop that has no side-effects +/// is easily detected and eliminated), but is often a big win for debug builds. +/// +/// Note that `ptr::drop_in_place` already performs this check, so if your workload +/// can be reduced to some small number of drop_in_place calls, using this is +/// unnecessary. In particular note that you can drop_in_place a slice, and that +/// will do a single needs_drop check for all the values. +/// +/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using +/// needs_drop explicitly. Types like `HashMap`, on the other hand, have to drop +/// values one at a time and should use this API. +/// +/// +/// # Examples +/// +/// Here's an example of how a collection might make use of `needs_drop`: +/// +/// ``` +/// use std::{mem, ptr}; +/// +/// pub struct MyCollection { +/// # data: [T; 1], +/// /* ... */ +/// } +/// # impl MyCollection { +/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data } +/// # fn free_buffer(&mut self) {} +/// # } +/// +/// impl Drop for MyCollection { +/// fn drop(&mut self) { +/// unsafe { +/// // drop the data +/// if mem::needs_drop::() { +/// for x in self.iter_mut() { +/// ptr::drop_in_place(x); +/// } +/// } +/// self.free_buffer(); +/// } +/// } +/// } +/// ``` +#[inline] +#[stable(feature = "needs_drop", since = "1.21.0")] +pub const fn needs_drop() -> bool { + intrinsics::needs_drop::() +} + +/// Creates a value whose bytes are all zero. +/// +/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. +/// It is useful for FFI sometimes, but should generally be avoided. +/// +/// There is no guarantee that an all-zero byte-pattern represents a valid value of +/// some type `T`. For example, the all-zero byte-pattern is not a valid value +/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types +/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv] +/// that there always is a valid value in a variable it considers initialized. +/// +/// [zeroed]: union.MaybeUninit.html#method.zeroed +/// [ub]: ../../reference/behavior-considered-undefined.html +/// [inv]: union.MaybeUninit.html#initialization-invariant +/// +/// # Examples +/// +/// Correct usage of this function: initializing an integer with zero. +/// +/// ``` +/// use std::mem; +/// +/// let x: i32 = unsafe { mem::zeroed() }; +/// assert_eq!(0, x); +/// ``` +/// +/// *Incorrect* usage of this function: initializing a reference with zero. +/// +/// ```no_run +/// use std::mem; +/// +/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub unsafe fn zeroed() -> T { + intrinsics::panic_if_uninhabited::(); + intrinsics::init() +} + +/// Bypasses Rust's normal memory-initialization checks by pretending to +/// produce a value of type `T`, while doing nothing at all. +/// +/// **This functon is deprecated.** Use [`MaybeUninit`] instead. +/// +/// The reason for deprecation is that the function basically cannot be used +/// correctly: [the Rust compiler assumes][inv] that values are properly initialized. +/// As a consequence, calling e.g. `mem::uninitialized::()` causes immediate +/// undefined behavior for returning a `bool` that is not definitely either `true` +/// or `false`. Worse, truly uninitialized memory like what gets returned here +/// is special in that the compiler knows that it does not have a fixed value. +/// This makes it undefined behavior to have uninitialized data in a variable even +/// if that variable has an integer type. +/// (Notice that the rules around uninitialized integers are not finalized yet, but +/// until they are, it is advisable to avoid them.) +/// +/// [`MaybeUninit`]: union.MaybeUninit.html +/// [inv]: union.MaybeUninit.html#initialization-invariant +#[inline] +#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")] +#[stable(feature = "rust1", since = "1.0.0")] +pub unsafe fn uninitialized() -> T { + intrinsics::panic_if_uninhabited::(); + intrinsics::uninit() +} + +/// Swaps the values at two mutable locations, without deinitializing either one. +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// let mut x = 5; +/// let mut y = 42; +/// +/// mem::swap(&mut x, &mut y); +/// +/// assert_eq!(42, x); +/// assert_eq!(5, y); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn swap(x: &mut T, y: &mut T) { + unsafe { + ptr::swap_nonoverlapping_one(x, y); + } +} + +/// Replace `dest` with the default value of `T`, and return the previous `dest` value. +/// +/// # Examples +/// +/// A simple example: +/// +/// ``` +/// #![feature(mem_take)] +/// +/// use std::mem; +/// +/// let mut v: Vec = vec![1, 2]; +/// +/// let old_v = mem::take(&mut v); +/// assert_eq!(vec![1, 2], old_v); +/// assert!(v.is_empty()); +/// ``` +/// +/// `take` allows taking ownership of a struct field by replacing it with an "empty" value. +/// Without `take` you can run into issues like these: +/// +/// ```compile_fail,E0507 +/// struct Buffer { buf: Vec } +/// +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// // error: cannot move out of dereference of `&mut`-pointer +/// let buf = self.buf; +/// self.buf = Vec::new(); +/// buf +/// } +/// } +/// ``` +/// +/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset +/// `self.buf`. But `take` can be used to disassociate the original value of `self.buf` from +/// `self`, allowing it to be returned: +/// +/// ``` +/// #![feature(mem_take)] +/// +/// use std::mem; +/// +/// # struct Buffer { buf: Vec } +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// mem::take(&mut self.buf) +/// } +/// } +/// ``` +/// +/// [`Clone`]: ../../std/clone/trait.Clone.html +#[inline] +#[unstable(feature = "mem_take", issue = "61129")] +pub fn take(dest: &mut T) -> T { + replace(dest, T::default()) +} + +/// Moves `src` into the referenced `dest`, returning the previous `dest` value. +/// +/// Neither value is dropped. +/// +/// # Examples +/// +/// A simple example: +/// +/// ``` +/// use std::mem; +/// +/// let mut v: Vec = vec![1, 2]; +/// +/// let old_v = mem::replace(&mut v, vec![3, 4, 5]); +/// assert_eq!(vec![1, 2], old_v); +/// assert_eq!(vec![3, 4, 5], v); +/// ``` +/// +/// `replace` allows consumption of a struct field by replacing it with another value. +/// Without `replace` you can run into issues like these: +/// +/// ```compile_fail,E0507 +/// struct Buffer { buf: Vec } +/// +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// // error: cannot move out of dereference of `&mut`-pointer +/// let buf = self.buf; +/// self.buf = Vec::new(); +/// buf +/// } +/// } +/// ``` +/// +/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset +/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from +/// `self`, allowing it to be returned: +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::mem; +/// +/// # struct Buffer { buf: Vec } +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// mem::replace(&mut self.buf, Vec::new()) +/// } +/// } +/// ``` +/// +/// [`Clone`]: ../../std/clone/trait.Clone.html +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn replace(dest: &mut T, mut src: T) -> T { + swap(dest, &mut src); + src +} + +/// Disposes of a value. +/// +/// This does call the argument's implementation of [`Drop`][drop]. +/// +/// This effectively does nothing for types which implement `Copy`, e.g. +/// integers. Such values are copied and _then_ moved into the function, so the +/// value persists after this function call. +/// +/// This function is not magic; it is literally defined as +/// +/// ``` +/// pub fn drop(_x: T) { } +/// ``` +/// +/// Because `_x` is moved into the function, it is automatically dropped before +/// the function returns. +/// +/// [drop]: ../ops/trait.Drop.html +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// +/// drop(v); // explicitly drop the vector +/// ``` +/// +/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can +/// release a [`RefCell`] borrow: +/// +/// ``` +/// use std::cell::RefCell; +/// +/// let x = RefCell::new(1); +/// +/// let mut mutable_borrow = x.borrow_mut(); +/// *mutable_borrow = 1; +/// +/// drop(mutable_borrow); // relinquish the mutable borrow on this slot +/// +/// let borrow = x.borrow(); +/// println!("{}", *borrow); +/// ``` +/// +/// Integers and other types implementing [`Copy`] are unaffected by `drop`. +/// +/// ``` +/// #[derive(Copy, Clone)] +/// struct Foo(u8); +/// +/// let x = 1; +/// let y = Foo(2); +/// drop(x); // a copy of `x` is moved and dropped +/// drop(y); // a copy of `y` is moved and dropped +/// +/// println!("x: {}, y: {}", x, y.0); // still available +/// ``` +/// +/// [`RefCell`]: ../../std/cell/struct.RefCell.html +/// [`Copy`]: ../../std/marker/trait.Copy.html +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn drop(_x: T) { } + +/// Interprets `src` as having type `&U`, and then reads `src` without moving +/// the contained value. +/// +/// This function will unsafely assume the pointer `src` is valid for +/// [`size_of::`][size_of] bytes by transmuting `&T` to `&U` and then reading +/// the `&U`. It will also unsafely create a copy of the contained value instead of +/// moving out of `src`. +/// +/// It is not a compile-time error if `T` and `U` have different sizes, but it +/// is highly encouraged to only invoke this function where `T` and `U` have the +/// same size. This function triggers [undefined behavior][ub] if `U` is larger than +/// `T`. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html +/// [size_of]: fn.size_of.html +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// #[repr(packed)] +/// struct Foo { +/// bar: u8, +/// } +/// +/// let foo_slice = [10u8]; +/// +/// unsafe { +/// // Copy the data from 'foo_slice' and treat it as a 'Foo' +/// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice); +/// assert_eq!(foo_struct.bar, 10); +/// +/// // Modify the copied data +/// foo_struct.bar = 20; +/// assert_eq!(foo_struct.bar, 20); +/// } +/// +/// // The contents of 'foo_slice' should not have changed +/// assert_eq!(foo_slice, [10]); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub unsafe fn transmute_copy(src: &T) -> U { + ptr::read_unaligned(src as *const T as *const U) +} + +/// Opaque type representing the discriminant of an enum. +/// +/// See the [`discriminant`] function in this module for more information. +/// +/// [`discriminant`]: fn.discriminant.html +#[stable(feature = "discriminant_value", since = "1.21.0")] +pub struct Discriminant(u64, PhantomData T>); + +// N.B. These trait implementations cannot be derived because we don't want any bounds on T. + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl Copy for Discriminant {} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl clone::Clone for Discriminant { + fn clone(&self) -> Self { + *self + } +} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl cmp::PartialEq for Discriminant { + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } +} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl cmp::Eq for Discriminant {} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl hash::Hash for Discriminant { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl fmt::Debug for Discriminant { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Discriminant") + .field(&self.0) + .finish() + } +} + +/// Returns a value uniquely identifying the enum variant in `v`. +/// +/// If `T` is not an enum, calling this function will not result in undefined behavior, but the +/// return value is unspecified. +/// +/// # Stability +/// +/// The discriminant of an enum variant may change if the enum definition changes. A discriminant +/// of some variant will not change between compilations with the same compiler. +/// +/// # Examples +/// +/// This can be used to compare enums that carry data, while disregarding +/// the actual data: +/// +/// ``` +/// use std::mem; +/// +/// enum Foo { A(&'static str), B(i32), C(i32) } +/// +/// assert!(mem::discriminant(&Foo::A("bar")) == mem::discriminant(&Foo::A("baz"))); +/// assert!(mem::discriminant(&Foo::B(1)) == mem::discriminant(&Foo::B(2))); +/// assert!(mem::discriminant(&Foo::B(3)) != mem::discriminant(&Foo::C(3))); +/// ``` +#[stable(feature = "discriminant_value", since = "1.21.0")] +pub fn discriminant(v: &T) -> Discriminant { + unsafe { + Discriminant(intrinsics::discriminant_value(v), PhantomData) + } +} diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 3f8d142c84..0bcd371b52 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -7,6 +7,9 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(test))] +use crate::intrinsics; + use crate::mem; use crate::num::FpCategory; @@ -372,15 +375,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f32) -> f32 { - // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the - // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it - // is either x or y, canonicalized (this means results might differ among implementations). - // When either x or y is a signalingNaN, then the result is according to 6.2. - // - // Since we do not support sNaN in Rust yet, we do not need to handle them. - // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by - // multiplying by 1.0. Should switch to the `canonicalize` when it works. - (if self.is_nan() || self < other { other } else { self }) * 1.0 + intrinsics::maxnumf32(self, other) } /// Returns the minimum of the two numbers. @@ -396,15 +391,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f32) -> f32 { - // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the - // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it - // is either x or y, canonicalized (this means results might differ among implementations). - // When either x or y is a signalingNaN, then the result is according to 6.2. - // - // Since we do not support sNaN in Rust yet, we do not need to handle them. - // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by - // multiplying by 1.0. Should switch to the `canonicalize` when it works. - (if other.is_nan() || self < other { self } else { other }) * 1.0 + intrinsics::minnumf32(self, other) } /// Raw transmutation to `u32`. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 7f19101fe6..4d4a2c9c5a 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -7,6 +7,9 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(test))] +use crate::intrinsics; + use crate::mem; use crate::num::FpCategory; @@ -385,15 +388,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f64) -> f64 { - // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the - // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it - // is either x or y, canonicalized (this means results might differ among implementations). - // When either x or y is a signalingNaN, then the result is according to 6.2. - // - // Since we do not support sNaN in Rust yet, we do not need to handle them. - // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by - // multiplying by 1.0. Should switch to the `canonicalize` when it works. - (if self.is_nan() || self < other { other } else { self }) * 1.0 + intrinsics::maxnumf64(self, other) } /// Returns the minimum of the two numbers. @@ -409,15 +404,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f64) -> f64 { - // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the - // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it - // is either x or y, canonicalized (this means results might differ among implementations). - // When either x or y is a signalingNaN, then the result is according to 6.2. - // - // Since we do not support sNaN in Rust yet, we do not need to handle them. - // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by - // multiplying by 1.0. Should switch to the `canonicalize` when it works. - (if other.is_nan() || self < other { self } else { other }) * 1.0 + intrinsics::minnumf64(self, other) } /// Raw transmutation to `u64`. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 562a7a4b3c..d70f556701 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -50,6 +50,7 @@ assert_eq!(size_of::>(), size_of::<", s #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] + #[cfg_attr(not(bootstrap), rustc_nonnull_optimization_guaranteed)] pub struct $Ty($Int); } @@ -462,16 +463,14 @@ assert_eq!(m, ", $swapped, "); Basic usage: ``` -#![feature(reverse_bits)] - let n = ", $swap_op, stringify!($SelfT), "; let m = n.reverse_bits(); assert_eq!(m, ", $reversed, "); ```"), - #[unstable(feature = "reverse_bits", issue = "48763")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[stable(feature = "reverse_bits", since = "1.37.0")] #[inline] + #[must_use] pub const fn reverse_bits(self) -> Self { (self as $UnsignedT).reverse_bits() as Self } @@ -1994,13 +1993,10 @@ assert_eq!((-10", stringify!($SelfT), ").signum(), -1);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_sign")] #[inline] - pub fn signum(self) -> Self { - match self { - n if n > 0 => 1, - 0 => 0, - _ => -1, - } + pub const fn signum(self) -> Self { + (self > 0) as Self - (self < 0) as Self } } @@ -2512,15 +2508,14 @@ assert_eq!(m, ", $swapped, "); Basic usage: ``` -#![feature(reverse_bits)] - let n = ", $swap_op, stringify!($SelfT), "; let m = n.reverse_bits(); assert_eq!(m, ", $reversed, "); ```"), - #[unstable(feature = "reverse_bits", issue = "48763")] + #[stable(feature = "reverse_bits", since = "1.37.0")] #[inline] + #[must_use] pub const fn reverse_bits(self) -> Self { intrinsics::bitreverse(self as $ActualT) as Self } @@ -4171,8 +4166,8 @@ impl u8 { /// Checks if the value is an ASCII alphabetic character: /// - /// - U+0041 'A' ... U+005A 'Z', or - /// - U+0061 'a' ... U+007A 'z'. + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z'. /// /// # Examples /// @@ -4207,7 +4202,7 @@ impl u8 { } /// Checks if the value is an ASCII uppercase character: - /// U+0041 'A' ... U+005A 'Z'. + /// U+0041 'A' ..= U+005A 'Z'. /// /// # Examples /// @@ -4242,7 +4237,7 @@ impl u8 { } /// Checks if the value is an ASCII lowercase character: - /// U+0061 'a' ... U+007A 'z'. + /// U+0061 'a' ..= U+007A 'z'. /// /// # Examples /// @@ -4278,9 +4273,9 @@ impl u8 { /// Checks if the value is an ASCII alphanumeric character: /// - /// - U+0041 'A' ... U+005A 'Z', or - /// - U+0061 'a' ... U+007A 'z', or - /// - U+0030 '0' ... U+0039 '9'. + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z', or + /// - U+0030 '0' ..= U+0039 '9'. /// /// # Examples /// @@ -4315,7 +4310,7 @@ impl u8 { } /// Checks if the value is an ASCII decimal digit: - /// U+0030 '0' ... U+0039 '9'. + /// U+0030 '0' ..= U+0039 '9'. /// /// # Examples /// @@ -4351,9 +4346,9 @@ impl u8 { /// Checks if the value is an ASCII hexadecimal digit: /// - /// - U+0030 '0' ... U+0039 '9', or - /// - U+0041 'A' ... U+0046 'F', or - /// - U+0061 'a' ... U+0066 'f'. + /// - U+0030 '0' ..= U+0039 '9', or + /// - U+0041 'A' ..= U+0046 'F', or + /// - U+0061 'a' ..= U+0066 'f'. /// /// # Examples /// @@ -4389,10 +4384,10 @@ impl u8 { /// Checks if the value is an ASCII punctuation character: /// - /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or - /// - U+003A ... U+0040 `: ; < = > ? @`, or - /// - U+005B ... U+0060 ``[ \ ] ^ _ ` ``, or - /// - U+007B ... U+007E `{ | } ~` + /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or + /// - U+003A ..= U+0040 `: ; < = > ? @`, or + /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or + /// - U+007B ..= U+007E `{ | } ~` /// /// # Examples /// @@ -4427,7 +4422,7 @@ impl u8 { } /// Checks if the value is an ASCII graphic character: - /// U+0021 '!' ... U+007E '~'. + /// U+0021 '!' ..= U+007E '~'. /// /// # Examples /// @@ -4514,7 +4509,7 @@ impl u8 { } /// Checks if the value is an ASCII control character: - /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE. + /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE. /// Note that most ASCII whitespace characters are control /// characters, but SPACE is not. /// diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index a3491bc3dc..fd129a306d 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -511,7 +511,6 @@ assert_eq!(n.trailing_zeros(), 3); /// Basic usage: /// /// ``` - /// #![feature(reverse_bits)] /// use std::num::Wrapping; /// /// let n = Wrapping(0b0000000_01010101i16); @@ -522,8 +521,9 @@ assert_eq!(n.trailing_zeros(), 3); /// assert_eq!(m.0 as u16, 0b10101010_00000000); /// assert_eq!(m, Wrapping(-22016)); /// ``` - #[unstable(feature = "reverse_bits", issue = "48763")] + #[stable(feature = "reverse_bits", since = "1.37.0")] #[inline] + #[must_use] pub const fn reverse_bits(self) -> Self { Wrapping(self.0.reverse_bits()) } diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 8139305f53..3c009d644c 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -508,7 +508,7 @@ div_impl_float! { f32 f64 } pub trait Rem { /// The resulting type after applying the `%` operator. #[stable(feature = "rust1", since = "1.0.0")] - type Output = Self; + type Output; /// Performs the `%` operation. #[must_use] diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index e44a6c4d2a..ce0d3fd01f 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -23,9 +23,9 @@ /// * Values of type `&T` are coerced to values of type `&U` /// * `T` implicitly implements all the (immutable) methods of the type `U`. /// -/// For more details, visit [the chapter in *The Rust Programming Language*] -/// [book] as well as the reference sections on [the dereference operator] -/// [ref-deref-op], [method resolution] and [type coercions]. +/// For more details, visit [the chapter in *The Rust Programming Language*][book] +/// as well as the reference sections on [the dereference operator][ref-deref-op], +/// [method resolution] and [type coercions]. /// /// [book]: ../../book/ch15-02-deref.html /// [`DerefMut`]: trait.DerefMut.html @@ -113,9 +113,9 @@ impl Deref for &mut T { /// * Values of type `&mut T` are coerced to values of type `&mut U` /// * `T` implicitly implements all the (mutable) methods of the type `U`. /// -/// For more details, visit [the chapter in *The Rust Programming Language*] -/// [book] as well as the reference sections on [the dereference operator] -/// [ref-deref-op], [method resolution] and [type coercions]. +/// For more details, visit [the chapter in *The Rust Programming Language*][book] +/// as well as the reference sections on [the dereference operator][ref-deref-op], +/// [method resolution] and [type coercions]. /// /// [book]: ../../book/ch15-02-deref.html /// [`Deref`]: trait.Deref.html diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index a707f0cc06..1b4c4218cc 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -696,6 +696,29 @@ pub enum Bound { Unbounded, } +impl Bound<&T> { + /// Map a `Bound<&T>` to a `Bound` by cloning the contents of the bound. + /// + /// # Examples + /// + /// ``` + /// #![feature(bound_cloned)] + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((1..12).start_bound(), Included(&1)); + /// assert_eq!((1..12).start_bound().cloned(), Included(1)); + /// ``` + #[unstable(feature = "bound_cloned", issue = "61356")] + pub fn cloned(self) -> Bound { + match self { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(x) => Bound::Included(x.clone()), + Bound::Excluded(x) => Bound::Excluded(x.clone()), + } + } +} + #[stable(feature = "collections_range", since = "1.28.0")] /// `RangeBounds` is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index 7f81481ab5..8e46830084 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -71,7 +71,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// This is used for object safety, to check that a method's receiver type can be dispatched on. /// -/// example impl: +/// An example implementation of the trait: /// /// ``` /// # #![feature(dispatch_from_dyn, unsize)] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 6b7f491eff..eec4b149dd 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -145,7 +145,7 @@ use crate::pin::Pin; // which basically means it must be `Option`. /// The `Option` type. See [the module level documentation](index.html) for more. -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option { /// No value @@ -725,8 +725,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(option_xor)] - /// /// let x = Some(2); /// let y: Option = None; /// assert_eq!(x.xor(y), Some(2)); @@ -744,7 +742,7 @@ impl Option { /// assert_eq!(x.xor(y), None); /// ``` #[inline] - #[unstable(feature = "option_xor", issue = "50512")] + #[stable(feature = "option_xor", since = "1.37.0")] pub fn xor(self, optb: Option) -> Option { match (self, optb) { (Some(a), None) => Some(a), @@ -1040,6 +1038,25 @@ fn expect_failed(msg: &str) -> ! { // Trait implementations ///////////////////////////////////////////////////////////////////////////// +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Option { + #[inline] + fn clone(&self) -> Self { + match self { + Some(x) => Some(x.clone()), + None => None, + } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (Some(to), Some(from)) => to.clone_from(from), + (to, from) => *to = from.clone(), + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { /// Returns [`None`][Option::None]. diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 4ced860948..c063cee522 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -1,10 +1,10 @@ //! Types that pin data to its location in memory. //! -//! It is sometimes useful to have objects that are guaranteed to not move, +//! It is sometimes useful to have objects that are guaranteed not to move, //! in the sense that their placement in memory does not change, and can thus be relied upon. //! A prime example of such a scenario would be building self-referential structs, -//! since moving an object with pointers to itself will invalidate them, -//! which could cause undefined behavior. +//! as moving an object with pointers to itself will invalidate them, which could cause undefined +//! behavior. //! //! A [`Pin

`] ensures that the pointee of any pointer type `P` has a stable location in memory, //! meaning it cannot be moved elsewhere and its memory cannot be deallocated @@ -15,9 +15,10 @@ //! moving the values they contain: you can move out of a `Box`, or you can use [`mem::swap`]. //! [`Pin

`] wraps a pointer type `P`, so `Pin>` functions much like a regular `Box`: //! when a `Pin>` gets dropped, so do its contents, and the memory gets deallocated. -//! Similarily, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin

`] does not let clients +//! Similarly, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin

`] does not let clients //! actually obtain a `Box` or `&mut T` to pinned data, which implies that you cannot use //! operations such as [`mem::swap`]: +//! //! ``` //! use std::pin::Pin; //! fn swap_pins(x: Pin<&mut T>, y: Pin<&mut T>) { @@ -39,19 +40,19 @@ //! as a "`P`-style pointer" to a pinned `P::Target` -- so, a `Pin>` is //! an owned pointer to a pinned `T`, and a `Pin>` is a reference-counted //! pointer to a pinned `T`. -//! For correctness, [`Pin

`] relies on the [`Deref`] and [`DerefMut`] implementations -//! to not move out of their `self` parameter, and to only ever return a pointer -//! to pinned data when they are called on a pinned pointer. +//! For correctness, [`Pin

`] relies on the implementations of [`Deref`] and +//! [`DerefMut`] not to move out of their `self` parameter, and only ever to +//! return a pointer to pinned data when they are called on a pinned pointer. //! //! # `Unpin` //! -//! However, these restrictions are usually not necessary. Many types are always freely -//! movable, even when pinned, because they do not rely on having a stable address. -//! This includes all the basic types (like `bool`, `i32`, references) -//! as well as types consisting solely of these types. -//! Types that do not care about pinning implement the [`Unpin`] auto-trait, which -//! cancels the effect of [`Pin

`]. For `T: Unpin`, `Pin>` and `Box` function -//! identically, as do `Pin<&mut T>` and `&mut T`. +//! Many types are always freely movable, even when pinned, because they do not +//! rely on having a stable address. This includes all the basic types (like +//! `bool`, `i32`, and references) as well as types consisting solely of these +//! types. Types that do not care about pinning implement the [`Unpin`] +//! auto-trait, which cancels the effect of [`Pin

`]. For `T: Unpin`, +//! `Pin>` and `Box` function identically, as do `Pin<&mut T>` and +//! `&mut T`. //! //! Note that pinning and `Unpin` only affect the pointed-to type `P::Target`, not the pointer //! type `P` itself that got wrapped in `Pin

`. For example, whether or not `Box` is @@ -65,11 +66,11 @@ //! use std::marker::PhantomPinned; //! use std::ptr::NonNull; //! -//! // This is a self-referential struct since the slice field points to the data field. +//! // This is a self-referential struct because the slice field points to the data field. //! // We cannot inform the compiler about that with a normal reference, -//! // since this pattern cannot be described with the usual borrowing rules. -//! // Instead we use a raw pointer, though one which is known to not be null, -//! // since we know it's pointing at the string. +//! // as this pattern cannot be described with the usual borrowing rules. +//! // Instead we use a raw pointer, though one which is known not to be null, +//! // as we know it's pointing at the string. //! struct Unmovable { //! data: String, //! slice: NonNull, @@ -137,16 +138,17 @@ //! To make this work, not just moving the data is restricted; deallocating, repurposing, or //! otherwise invalidating the memory used to store the data is restricted, too. //! Concretely, for pinned data you have to maintain the invariant -//! that *its memory will not get invalidated from the moment it gets pinned until +//! that *its memory will not get invalidated or repurposed from the moment it gets pinned until //! when `drop` is called*. Memory can be invalidated by deallocation, but also by //! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements -//! off of a vector. +//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without +//! calling the destructor first. //! //! This is exactly the kind of guarantee that the intrusive linked list from the previous //! section needs to function correctly. //! //! Notice that this guarantee does *not* mean that memory does not leak! It is still -//! completely okay not to ever call `drop` on a pinned element (e.g., you can still +//! completely okay not ever to call `drop` on a pinned element (e.g., you can still //! call [`mem::forget`] on a `Pin>`). In the example of the doubly-linked //! list, that element would just stay in the list. However you may not free or reuse the storage //! *without calling `drop`*. @@ -165,57 +167,130 @@ //! implementation as well: if an element of your type could have been pinned, //! you must treat Drop as implicitly taking `Pin<&mut Self>`. //! -//! In particular, if your type is `#[repr(packed)]`, the compiler will automatically +//! For example, you could implement `Drop` as follows: +//! ```rust,no_run +//! # use std::pin::Pin; +//! # struct Type { } +//! impl Drop for Type { +//! fn drop(&mut self) { +//! // `new_unchecked` is okay because we know this value is never used +//! // again after being dropped. +//! inner_drop(unsafe { Pin::new_unchecked(self)}); +//! fn inner_drop(this: Pin<&mut Type>) { +//! // Actual drop code goes here. +//! } +//! } +//! } +//! ``` +//! The function `inner_drop` has the type that `drop` *should* have, so this makes sure that +//! you do not accidentally use `self`/`this` in a way that is in conflict with pinning. +//! +//! Moreover, if your type is `#[repr(packed)]`, the compiler will automatically //! move fields around to be able to drop them. As a consequence, you cannot use //! pinning with a `#[repr(packed)]` type. //! //! # Projections and Structural Pinning //! -//! One interesting question arises when considering the interaction of pinning -//! and the fields of a struct. When can a struct have a "pinning projection", -//! i.e., an operation with type `fn(Pin<&Struct>) -> Pin<&Field>`? In a -//! similar vein, when can a generic wrapper type (such as `Vec`, `Box`, -//! or `RefCell`) have an operation with type `fn(Pin<&Wrapper>) -> -//! Pin<&T>`? -//! -//! Note: For the entirety of this discussion, the same applies for mutable references as it -//! does for shared references. +//! When working with pinned structs, the question arises how one can access the +//! fields of that struct in a method that takes just `Pin<&mut Struct>`. +//! The usual approach is to write helper methods (so called *projections*) +//! that turn `Pin<&mut Struct>` into a reference to the field, but what +//! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`? +//! The same question arises with the fields of an `enum`, and also when considering +//! container/wrapper types such as [`Vec`], [`Box`], or [`RefCell`]. +//! (This question applies to both mutable and shared references, we just +//! use the more common case of mutable references here for illustration.) +//! +//! It turns out that it is actually up to the author of the data structure +//! to decide whether the pinned projection for a particular field turns +//! `Pin<&mut Struct>` into `Pin<&mut Field>` or `&mut Field`. There are some +//! constraints though, and the most important constraint is *consistency*: +//! every field can be *either* projected to a pinned reference, *or* have +//! pinning removed as part of the projection. If both are done for the same field, +//! that will likely be unsound! +//! +//! As the author of a data structure you get to decide for each field whether pinning +//! "propagates" to this field or not. Pinning that propagates is also called "structural", +//! because it follows the structure of the type. +//! In the following subsections, we describe the considerations that have to be made +//! for either choice. +//! +//! ## Pinning *is not* structural for `field` +//! +//! It may seem counter-intuitive that the field of a pinned struct might not be pinned, +//! but that is actually the easiest choice: if a `Pin<&mut Field>` is never created, +//! nothing can go wrong! So, if you decide that some field does not have structural pinning, +//! all you have to ensure is that you never create a pinned reference to that field. +//! +//! Fields without structural pinning may have a projection method that turns +//! `Pin<&mut Struct>` into `&mut Field`: +//! ```rust,no_run +//! # use std::pin::Pin; +//! # type Field = i32; +//! # struct Struct { field: Field } +//! impl Struct { +//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field { +//! // This is okay because `field` is never considered pinned. +//! unsafe { &mut self.get_unchecked_mut().field } +//! } +//! } +//! ``` //! -//! Having a pinning projection for some field means that pinning is "structural": -//! when the wrapper is pinned, the field must be considered pinned, too. -//! After all, the pinning projection lets us get a `Pin<&Field>`. +//! You may also `impl Unpin for Struct` *even if* the type of `field` +//! is not `Unpin`. What that type thinks about pinning is not relevant +//! when no `Pin<&mut Field>` is ever created. +//! +//! ## Pinning *is* structural for `field` +//! +//! The other option is to decide that pinning is "structural" for `field`, +//! meaning that if the struct is pinned then so is the field. +//! +//! This allows writing a projection that creates a `Pin<&mut Field>`, thus +//! witnessing that the field is pinned: +//! ```rust,no_run +//! # use std::pin::Pin; +//! # type Field = i32; +//! # struct Struct { field: Field } +//! impl Struct { +//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> { +//! // This is okay because `field` is pinned when `self` is. +//! unsafe { self.map_unchecked_mut(|s| &mut s.field) } +//! } +//! } +//! ``` //! -//! However, structural pinning comes with a few extra requirements, so not all -//! wrappers can be structural and hence not all wrappers can offer pinning projections: +//! However, structural pinning comes with a few extra requirements: //! -//! 1. The wrapper must only be [`Unpin`] if all the structural fields are +//! 1. The struct must only be [`Unpin`] if all the structural fields are //! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of -//! the wrapper it is your responsibility *not* to add something like -//! `impl Unpin for Wrapper`. (Notice that adding a projection operation -//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break +//! the struct it is your responsibility *not* to add something like +//! `impl Unpin for Struct`. (Notice that adding a projection operation +//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break //! the principle that you only have to worry about any of this if you use `unsafe`.) -//! 2. The destructor of the wrapper must not move structural fields out of its argument. This +//! 2. The destructor of the struct must not move structural fields out of its argument. This //! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes -//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before. +//! `&mut self`, but the struct (and hence its fields) might have been pinned before. //! You have to guarantee that you do not move a field inside your `Drop` implementation. -//! In particular, as explained previously, this means that your wrapper type must *not* +//! In particular, as explained previously, this means that your struct must *not* //! be `#[repr(packed)]`. +//! See that section for how to write `drop` in a way that the compiler can help you +//! not accidentally break pinning. //! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]: -//! once your wrapper is pinned, the memory that contains the +//! once your struct is pinned, the memory that contains the //! content is not overwritten or deallocated without calling the content's destructors. -//! This can be tricky, as witnessed by `VecDeque`: the destructor of `VecDeque` can fail -//! to call `drop` on all elements if one of the destructors panics. This violates the +//! This can be tricky, as witnessed by [`VecDeque`]: the destructor of `VecDeque` +//! can fail to call `drop` on all elements if one of the destructors panics. This violates the //! `Drop` guarantee, because it can lead to elements being deallocated without //! their destructor being called. (`VecDeque` has no pinning projections, so this //! does not cause unsoundness.) //! 4. You must not offer any other operations that could lead to data being moved out of -//! the fields when your type is pinned. For example, if the wrapper contains an +//! the structural fields when your type is pinned. For example, if the struct contains an //! `Option` and there is a `take`-like operation with type -//! `fn(Pin<&mut Wrapper>) -> Option`, -//! that operation can be used to move a `T` out of a pinned `Wrapper` -- which means -//! pinning cannot be structural. +//! `fn(Pin<&mut Struct>) -> Option`, +//! that operation can be used to move a `T` out of a pinned `Struct` -- which means +//! pinning cannot be structural for the field holding this data. //! -//! For a more complex example of moving data out of a pinned type, imagine if `RefCell` +//! For a more complex example of moving data out of a pinned type, imagine if [`RefCell`] //! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`. //! Then we could do the following: //! ```compile_fail @@ -230,13 +305,16 @@ //! (using `RefCell::get_pin_mut`) and then move that content using the mutable //! reference we got later. //! -//! For a type like `Vec`, both possibilites (structural pinning or not) make sense, -//! and the choice is up to the author. A `Vec` with structural pinning could -//! have `get_pin`/`get_pin_mut` projections. However, it could *not* allow calling +//! ## Examples +//! +//! For a type like [`Vec`], both possibilites (structural pinning or not) make sense. +//! A `Vec` with structural pinning could have `get_pin`/`get_pin_mut` methods to get +//! pinned references to elements. However, it could *not* allow calling //! `pop` on a pinned `Vec` because that would move the (structurally pinned) contents! //! Nor could it allow `push`, which might reallocate and thus also move the contents. //! A `Vec` without structural pinning could `impl Unpin for Vec`, because the contents //! are never pinned and the `Vec` itself is fine with being moved as well. +//! At that point pinning just has no effect on the vector at all. //! //! In the standard library, pointer types generally do not have structural pinning, //! and thus they do not offer pinning projections. This is why `Box: Unpin` holds for all `T`. @@ -248,16 +326,28 @@ //! whether the content is pinned is entirely independent of whether the pointer is //! pinned, meaning pinning is *not* structural. //! +//! When implementing a [`Future`] combinator, you will usually need structural pinning +//! for the nested futures, as you need to get pinned references to them to call `poll`. +//! But if your combinator contains any other data that does not need to be pinned, +//! you can make those fields not structural and hence freely access them with a +//! mutable reference even when you just have `Pin<&mut Self>` (such as in your own +//! `poll` implementation). +//! //! [`Pin

`]: struct.Pin.html -//! [`Unpin`]: ../../std/marker/trait.Unpin.html -//! [`Deref`]: ../../std/ops/trait.Deref.html -//! [`DerefMut`]: ../../std/ops/trait.DerefMut.html -//! [`mem::swap`]: ../../std/mem/fn.swap.html -//! [`mem::forget`]: ../../std/mem/fn.forget.html +//! [`Unpin`]: ../marker/trait.Unpin.html +//! [`Deref`]: ../ops/trait.Deref.html +//! [`DerefMut`]: ../ops/trait.DerefMut.html +//! [`mem::swap`]: ../mem/fn.swap.html +//! [`mem::forget`]: ../mem/fn.forget.html //! [`Box`]: ../../std/boxed/struct.Box.html +//! [`Vec`]: ../../std/vec/struct.Vec.html //! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len -//! [`None`]: ../../std/option/enum.Option.html#variant.None -//! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some +//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html +//! [`RefCell`]: ../cell/struct.RefCell.html +//! [`None`]: ../option/enum.Option.html#variant.None +//! [`Some(v)`]: ../option/enum.Option.html#variant.Some +//! [`ptr::write`]: ../ptr/fn.write.html +//! [`Future`]: ../future/trait.Future.html //! [drop-impl]: #drop-implementation //! [drop-guarantee]: #drop-guarantee diff --git a/src/libcore/ptr.rs b/src/libcore/ptr/mod.rs similarity index 87% rename from src/libcore/ptr.rs rename to src/libcore/ptr/mod.rs index 006b1e143e..fccb00d768 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr/mod.rs @@ -1,5 +1,3 @@ -// ignore-tidy-filelength - //! Manually manage memory through raw pointers. //! //! *[See also the pointer primitive types](../../std/primitive.pointer.html).* @@ -65,14 +63,10 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::convert::From; use crate::intrinsics; -use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::fmt; use crate::hash; -use crate::marker::{PhantomData, Unsize}; use crate::mem::{self, MaybeUninit}; - use crate::cmp::Ordering::{self, Less, Equal, Greater}; #[stable(feature = "rust1", since = "1.0.0")] @@ -84,6 +78,14 @@ pub use crate::intrinsics::copy; #[stable(feature = "rust1", since = "1.0.0")] pub use crate::intrinsics::write_bytes; +mod non_null; +#[stable(feature = "nonnull", since = "1.25.0")] +pub use non_null::NonNull; + +mod unique; +#[unstable(feature = "ptr_internals", issue = "0")] +pub use unique::Unique; + /// Executes the destructor (if any) of the pointed-to value. /// /// This is semantically equivalent to calling [`ptr::read`] and discarding @@ -228,6 +230,53 @@ pub const fn null() -> *const T { 0 as *const T } #[rustc_promotable] pub const fn null_mut() -> *mut T { 0 as *mut T } +#[repr(C)] +pub(crate) union Repr { + pub(crate) rust: *const [T], + rust_mut: *mut [T], + pub(crate) raw: FatPtr, +} + +#[repr(C)] +pub(crate) struct FatPtr { + data: *const T, + pub(crate) len: usize, +} + +/// Forms a slice from a pointer and a length. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// +/// # Examples +/// +/// ```rust +/// #![feature(slice_from_raw_parts)] +/// use std::ptr; +/// +/// // create a slice pointer when starting out with a pointer to the first element +/// let mut x = [5, 6, 7]; +/// let ptr = &mut x[0] as *mut _; +/// let slice = ptr::slice_from_raw_parts_mut(ptr, 3); +/// assert_eq!(unsafe { &*slice }[2], 7); +/// ``` +#[inline] +#[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")] +pub fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { + unsafe { Repr { raw: FatPtr { data, len } }.rust } +} + +/// Performs the same functionality as [`from_raw_parts`], except that a +/// mutable slice is returned. +/// +/// See the documentation of [`from_raw_parts`] for more details. +/// +/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html +#[inline] +#[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")] +pub fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { + unsafe { Repr { raw: FatPtr { data, len } }.rust_mut } +} + /// Swaps the values at two mutable locations of the same type, without /// deinitializing either. /// @@ -982,8 +1031,17 @@ impl *const T { /// operation because the returned value could be pointing to invalid /// memory. /// + /// When calling this method, you have to ensure that if the pointer is + /// non-NULL, then it is properly aligned, dereferencable (for the whole + /// size of `T`) and points to an initialized instance of `T`. This applies + /// even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. + /// not necessarily reflect the actual lifetime of the data. It is up to the + /// caller to ensure that for the duration of this lifetime, the memory this + /// pointer points to does not get written to outside of `UnsafeCell`. /// /// # Examples /// @@ -1608,8 +1666,17 @@ impl *mut T { /// operation because the returned value could be pointing to invalid /// memory. /// + /// When calling this method, you have to ensure that if the pointer is + /// non-NULL, then it is properly aligned, dereferencable (for the whole + /// size of `T`) and points to an initialized instance of `T`. This applies + /// even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. + /// not necessarily reflect the actual lifetime of the data. It is up to the + /// caller to ensure that for the duration of this lifetime, the memory this + /// pointer points to does not get written to outside of `UnsafeCell`. /// /// # Examples /// @@ -1753,10 +1820,24 @@ impl *mut T { /// /// # Safety /// - /// As with `as_ref`, this is unsafe because it cannot verify the validity + /// As with [`as_ref`], this is unsafe because it cannot verify the validity /// of the returned pointer, nor can it ensure that the lifetime `'a` /// returned is indeed a valid lifetime for the contained data. /// + /// When calling this method, you have to ensure that if the pointer is + /// non-NULL, then it is properly aligned, dereferencable (for the whole + /// size of `T`) and points to an initialized instance of `T`. This applies + /// even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is the only safe approach is to ensure that they are indeed initialized.) + /// + /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does + /// not necessarily reflect the actual lifetime of the data. It is up to the + /// caller to ensure that for the duration of this lifetime, the memory this + /// pointer points to does not get accessed through any other pointer. + /// + /// [`as_ref`]: #method.as_ref + /// /// # Examples /// /// Basic usage: @@ -2644,12 +2725,12 @@ macro_rules! fnptr_impls_safety_abi { macro_rules! fnptr_impls_args { ($($Arg: ident),+) => { - fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),*) -> Ret, $($Arg),* } - fnptr_impls_safety_abi! { extern "C" fn($($Arg),*) -> Ret, $($Arg),* } - fnptr_impls_safety_abi! { extern "C" fn($($Arg),* , ...) -> Ret, $($Arg),* } - fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),*) -> Ret, $($Arg),* } - fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),*) -> Ret, $($Arg),* } - fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),* , ...) -> Ret, $($Arg),* } + fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ } + fnptr_impls_safety_abi! { extern "C" fn($($Arg),+) -> Ret, $($Arg),+ } + fnptr_impls_safety_abi! { extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ } + fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ } + fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+) -> Ret, $($Arg),+ } + fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ } }; () => { // No variadic functions with 0 parameters @@ -2742,383 +2823,3 @@ impl PartialOrd for *mut T { #[inline] fn ge(&self, other: &*mut T) -> bool { *self >= *other } } - -/// A wrapper around a raw non-null `*mut T` that indicates that the possessor -/// of this wrapper owns the referent. Useful for building abstractions like -/// `Box`, `Vec`, `String`, and `HashMap`. -/// -/// Unlike `*mut T`, `Unique` behaves "as if" it were an instance of `T`. -/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies -/// the kind of strong aliasing guarantees an instance of `T` can expect: -/// the referent of the pointer should not be modified without a unique path to -/// its owning Unique. -/// -/// If you're uncertain of whether it's correct to use `Unique` for your purposes, -/// consider using `NonNull`, which has weaker semantics. -/// -/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer -/// is never dereferenced. This is so that enums may use this forbidden value -/// as a discriminant -- `Option>` has the same size as `Unique`. -/// However the pointer may still dangle if it isn't dereferenced. -/// -/// Unlike `*mut T`, `Unique` is covariant over `T`. This should always be correct -/// for any type which upholds Unique's aliasing requirements. -#[unstable(feature = "ptr_internals", issue = "0", - reason = "use NonNull instead and consider PhantomData \ - (if you also use #[may_dangle]), Send, and/or Sync")] -#[doc(hidden)] -#[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(1)] -pub struct Unique { - pointer: *const T, - // NOTE: this marker has no consequences for variance, but is necessary - // for dropck to understand that we logically own a `T`. - // - // For details, see: - // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data - _marker: PhantomData, -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl fmt::Debug for Unique { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.as_ptr(), f) - } -} - -/// `Unique` pointers are `Send` if `T` is `Send` because the data they -/// reference is unaliased. Note that this aliasing invariant is -/// unenforced by the type system; the abstraction using the -/// `Unique` must enforce it. -#[unstable(feature = "ptr_internals", issue = "0")] -unsafe impl Send for Unique { } - -/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they -/// reference is unaliased. Note that this aliasing invariant is -/// unenforced by the type system; the abstraction using the -/// `Unique` must enforce it. -#[unstable(feature = "ptr_internals", issue = "0")] -unsafe impl Sync for Unique { } - -#[unstable(feature = "ptr_internals", issue = "0")] -impl Unique { - /// Creates a new `Unique` that is dangling, but well-aligned. - /// - /// This is useful for initializing types which lazily allocate, like - /// `Vec::new` does. - /// - /// Note that the pointer value may potentially represent a valid pointer to - /// a `T`, which means this must not be used as a "not yet initialized" - /// sentinel value. Types that lazily allocate must track initialization by - /// some other means. - // FIXME: rename to dangling() to match NonNull? - pub const fn empty() -> Self { - unsafe { - Unique::new_unchecked(mem::align_of::() as *mut T) - } - } -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl Unique { - /// Creates a new `Unique`. - /// - /// # Safety - /// - /// `ptr` must be non-null. - pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { - Unique { pointer: ptr as _, _marker: PhantomData } - } - - /// Creates a new `Unique` if `ptr` is non-null. - pub fn new(ptr: *mut T) -> Option { - if !ptr.is_null() { - Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }) - } else { - None - } - } - - /// Acquires the underlying `*mut` pointer. - pub const fn as_ptr(self) -> *mut T { - self.pointer as *mut T - } - - /// Dereferences the content. - /// - /// The resulting lifetime is bound to self so this behaves "as if" - /// it were actually an instance of T that is getting borrowed. If a longer - /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. - pub unsafe fn as_ref(&self) -> &T { - &*self.as_ptr() - } - - /// Mutably dereferences the content. - /// - /// The resulting lifetime is bound to self so this behaves "as if" - /// it were actually an instance of T that is getting borrowed. If a longer - /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. - pub unsafe fn as_mut(&mut self) -> &mut T { - &mut *self.as_ptr() - } -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl Clone for Unique { - fn clone(&self) -> Self { - *self - } -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl Copy for Unique { } - -#[unstable(feature = "ptr_internals", issue = "0")] -impl CoerceUnsized> for Unique where T: Unsize { } - -#[unstable(feature = "ptr_internals", issue = "0")] -impl DispatchFromDyn> for Unique where T: Unsize { } - -#[unstable(feature = "ptr_internals", issue = "0")] -impl fmt::Pointer for Unique { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.as_ptr(), f) - } -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl From<&mut T> for Unique { - fn from(reference: &mut T) -> Self { - unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } } - } -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl From<&T> for Unique { - fn from(reference: &T) -> Self { - unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } } - } -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl<'a, T: ?Sized> From> for Unique { - fn from(p: NonNull) -> Self { - unsafe { Unique { pointer: p.pointer, _marker: PhantomData } } - } -} - -/// `*mut T` but non-zero and covariant. -/// -/// This is often the correct thing to use when building data structures using -/// raw pointers, but is ultimately more dangerous to use because of its additional -/// properties. If you're not sure if you should use `NonNull`, just use `*mut T`! -/// -/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer -/// is never dereferenced. This is so that enums may use this forbidden value -/// as a discriminant -- `Option>` has the same size as `*mut T`. -/// However the pointer may still dangle if it isn't dereferenced. -/// -/// Unlike `*mut T`, `NonNull` is covariant over `T`. If this is incorrect -/// for your use case, you should include some [`PhantomData`] in your type to -/// provide invariance, such as `PhantomData>` or `PhantomData<&'a mut T>`. -/// Usually this won't be necessary; covariance is correct for most safe abstractions, -/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they -/// provide a public API that follows the normal shared XOR mutable rules of Rust. -/// -/// Notice that `NonNull` has a `From` instance for `&T`. However, this does -/// not change the fact that mutating through a (pointer derived from a) shared -/// reference is undefined behavior unless the mutation happens inside an -/// [`UnsafeCell`]. The same goes for creating a mutable reference from a shared -/// reference. When using this `From` instance without an `UnsafeCell`, -/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` -/// is never used for mutation. -/// -/// [`PhantomData`]: ../marker/struct.PhantomData.html -/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html -#[stable(feature = "nonnull", since = "1.25.0")] -#[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(1)] -pub struct NonNull { - pointer: *const T, -} - -/// `NonNull` pointers are not `Send` because the data they reference may be aliased. -// N.B., this impl is unnecessary, but should provide better error messages. -#[stable(feature = "nonnull", since = "1.25.0")] -impl !Send for NonNull { } - -/// `NonNull` pointers are not `Sync` because the data they reference may be aliased. -// N.B., this impl is unnecessary, but should provide better error messages. -#[stable(feature = "nonnull", since = "1.25.0")] -impl !Sync for NonNull { } - -impl NonNull { - /// Creates a new `NonNull` that is dangling, but well-aligned. - /// - /// This is useful for initializing types which lazily allocate, like - /// `Vec::new` does. - /// - /// Note that the pointer value may potentially represent a valid pointer to - /// a `T`, which means this must not be used as a "not yet initialized" - /// sentinel value. Types that lazily allocate must track initialization by - /// some other means. - #[stable(feature = "nonnull", since = "1.25.0")] - #[inline] - pub const fn dangling() -> Self { - unsafe { - let ptr = mem::align_of::() as *mut T; - NonNull::new_unchecked(ptr) - } - } -} - -impl NonNull { - /// Creates a new `NonNull`. - /// - /// # Safety - /// - /// `ptr` must be non-null. - #[stable(feature = "nonnull", since = "1.25.0")] - #[inline] - pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { - NonNull { pointer: ptr as _ } - } - - /// Creates a new `NonNull` if `ptr` is non-null. - #[stable(feature = "nonnull", since = "1.25.0")] - #[inline] - pub fn new(ptr: *mut T) -> Option { - if !ptr.is_null() { - Some(unsafe { Self::new_unchecked(ptr) }) - } else { - None - } - } - - /// Acquires the underlying `*mut` pointer. - #[stable(feature = "nonnull", since = "1.25.0")] - #[inline] - pub const fn as_ptr(self) -> *mut T { - self.pointer as *mut T - } - - /// Dereferences the content. - /// - /// The resulting lifetime is bound to self so this behaves "as if" - /// it were actually an instance of T that is getting borrowed. If a longer - /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. - #[stable(feature = "nonnull", since = "1.25.0")] - #[inline] - pub unsafe fn as_ref(&self) -> &T { - &*self.as_ptr() - } - - /// Mutably dereferences the content. - /// - /// The resulting lifetime is bound to self so this behaves "as if" - /// it were actually an instance of T that is getting borrowed. If a longer - /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. - #[stable(feature = "nonnull", since = "1.25.0")] - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - &mut *self.as_ptr() - } - - /// Cast to a pointer of another type - #[stable(feature = "nonnull_cast", since = "1.27.0")] - #[inline] - pub const fn cast(self) -> NonNull { - unsafe { - NonNull::new_unchecked(self.as_ptr() as *mut U) - } - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl Clone for NonNull { - fn clone(&self) -> Self { - *self - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl Copy for NonNull { } - -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl CoerceUnsized> for NonNull where T: Unsize { } - -#[unstable(feature = "dispatch_from_dyn", issue = "0")] -impl DispatchFromDyn> for NonNull where T: Unsize { } - -#[stable(feature = "nonnull", since = "1.25.0")] -impl fmt::Debug for NonNull { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.as_ptr(), f) - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl fmt::Pointer for NonNull { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.as_ptr(), f) - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl Eq for NonNull {} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl PartialEq for NonNull { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.as_ptr() == other.as_ptr() - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl Ord for NonNull { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - self.as_ptr().cmp(&other.as_ptr()) - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl PartialOrd for NonNull { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - self.as_ptr().partial_cmp(&other.as_ptr()) - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl hash::Hash for NonNull { - #[inline] - fn hash(&self, state: &mut H) { - self.as_ptr().hash(state) - } -} - -#[unstable(feature = "ptr_internals", issue = "0")] -impl From> for NonNull { - #[inline] - fn from(unique: Unique) -> Self { - unsafe { NonNull { pointer: unique.pointer } } - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl From<&mut T> for NonNull { - #[inline] - fn from(reference: &mut T) -> Self { - unsafe { NonNull { pointer: reference as *mut T } } - } -} - -#[stable(feature = "nonnull", since = "1.25.0")] -impl From<&T> for NonNull { - #[inline] - fn from(reference: &T) -> Self { - unsafe { NonNull { pointer: reference as *const T } } - } -} diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs new file mode 100644 index 0000000000..46dde7c1da --- /dev/null +++ b/src/libcore/ptr/non_null.rs @@ -0,0 +1,226 @@ +use crate::convert::From; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::fmt; +use crate::hash; +use crate::marker::Unsize; +use crate::mem; +use crate::ptr::Unique; +use crate::cmp::Ordering; + +/// `*mut T` but non-zero and covariant. +/// +/// This is often the correct thing to use when building data structures using +/// raw pointers, but is ultimately more dangerous to use because of its additional +/// properties. If you're not sure if you should use `NonNull`, just use `*mut T`! +/// +/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer +/// is never dereferenced. This is so that enums may use this forbidden value +/// as a discriminant -- `Option>` has the same size as `*mut T`. +/// However the pointer may still dangle if it isn't dereferenced. +/// +/// Unlike `*mut T`, `NonNull` is covariant over `T`. If this is incorrect +/// for your use case, you should include some [`PhantomData`] in your type to +/// provide invariance, such as `PhantomData>` or `PhantomData<&'a mut T>`. +/// Usually this won't be necessary; covariance is correct for most safe abstractions, +/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they +/// provide a public API that follows the normal shared XOR mutable rules of Rust. +/// +/// Notice that `NonNull` has a `From` instance for `&T`. However, this does +/// not change the fact that mutating through a (pointer derived from a) shared +/// reference is undefined behavior unless the mutation happens inside an +/// [`UnsafeCell`]. The same goes for creating a mutable reference from a shared +/// reference. When using this `From` instance without an `UnsafeCell`, +/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` +/// is never used for mutation. +/// +/// [`PhantomData`]: ../marker/struct.PhantomData.html +/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html +#[stable(feature = "nonnull", since = "1.25.0")] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(1)] +#[cfg_attr(not(bootstrap), rustc_nonnull_optimization_guaranteed)] +pub struct NonNull { + pointer: *const T, +} + +/// `NonNull` pointers are not `Send` because the data they reference may be aliased. +// N.B., this impl is unnecessary, but should provide better error messages. +#[stable(feature = "nonnull", since = "1.25.0")] +impl !Send for NonNull { } + +/// `NonNull` pointers are not `Sync` because the data they reference may be aliased. +// N.B., this impl is unnecessary, but should provide better error messages. +#[stable(feature = "nonnull", since = "1.25.0")] +impl !Sync for NonNull { } + +impl NonNull { + /// Creates a new `NonNull` that is dangling, but well-aligned. + /// + /// This is useful for initializing types which lazily allocate, like + /// `Vec::new` does. + /// + /// Note that the pointer value may potentially represent a valid pointer to + /// a `T`, which means this must not be used as a "not yet initialized" + /// sentinel value. Types that lazily allocate must track initialization by + /// some other means. + #[stable(feature = "nonnull", since = "1.25.0")] + #[inline] + pub const fn dangling() -> Self { + unsafe { + let ptr = mem::align_of::() as *mut T; + NonNull::new_unchecked(ptr) + } + } +} + +impl NonNull { + /// Creates a new `NonNull`. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[stable(feature = "nonnull", since = "1.25.0")] + #[inline] + pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { + NonNull { pointer: ptr as _ } + } + + /// Creates a new `NonNull` if `ptr` is non-null. + #[stable(feature = "nonnull", since = "1.25.0")] + #[inline] + pub fn new(ptr: *mut T) -> Option { + if !ptr.is_null() { + Some(unsafe { Self::new_unchecked(ptr) }) + } else { + None + } + } + + /// Acquires the underlying `*mut` pointer. + #[stable(feature = "nonnull", since = "1.25.0")] + #[inline] + pub const fn as_ptr(self) -> *mut T { + self.pointer as *mut T + } + + /// Dereferences the content. + /// + /// The resulting lifetime is bound to self so this behaves "as if" + /// it were actually an instance of T that is getting borrowed. If a longer + /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. + #[stable(feature = "nonnull", since = "1.25.0")] + #[inline] + pub unsafe fn as_ref(&self) -> &T { + &*self.as_ptr() + } + + /// Mutably dereferences the content. + /// + /// The resulting lifetime is bound to self so this behaves "as if" + /// it were actually an instance of T that is getting borrowed. If a longer + /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. + #[stable(feature = "nonnull", since = "1.25.0")] + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + &mut *self.as_ptr() + } + + /// Cast to a pointer of another type + #[stable(feature = "nonnull_cast", since = "1.27.0")] + #[inline] + pub const fn cast(self) -> NonNull { + unsafe { + NonNull::new_unchecked(self.as_ptr() as *mut U) + } + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Clone for NonNull { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Copy for NonNull { } + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl CoerceUnsized> for NonNull where T: Unsize { } + +#[unstable(feature = "dispatch_from_dyn", issue = "0")] +impl DispatchFromDyn> for NonNull where T: Unsize { } + +#[stable(feature = "nonnull", since = "1.25.0")] +impl fmt::Debug for NonNull { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl fmt::Pointer for NonNull { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Eq for NonNull {} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl PartialEq for NonNull { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.as_ptr() == other.as_ptr() + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Ord for NonNull { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.as_ptr().cmp(&other.as_ptr()) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl PartialOrd for NonNull { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.as_ptr().partial_cmp(&other.as_ptr()) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl hash::Hash for NonNull { + #[inline] + fn hash(&self, state: &mut H) { + self.as_ptr().hash(state) + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl From> for NonNull { + #[inline] + fn from(unique: Unique) -> Self { + unsafe { NonNull::new_unchecked(unique.as_ptr()) } + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl From<&mut T> for NonNull { + #[inline] + fn from(reference: &mut T) -> Self { + unsafe { NonNull { pointer: reference as *mut T } } + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl From<&T> for NonNull { + #[inline] + fn from(reference: &T) -> Self { + unsafe { NonNull { pointer: reference as *const T } } + } +} diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs new file mode 100644 index 0000000000..5911518919 --- /dev/null +++ b/src/libcore/ptr/unique.rs @@ -0,0 +1,180 @@ +use crate::convert::From; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::fmt; +use crate::marker::{PhantomData, Unsize}; +use crate::mem; +use crate::ptr::NonNull; + +/// A wrapper around a raw non-null `*mut T` that indicates that the possessor +/// of this wrapper owns the referent. Useful for building abstractions like +/// `Box`, `Vec`, `String`, and `HashMap`. +/// +/// Unlike `*mut T`, `Unique` behaves "as if" it were an instance of `T`. +/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies +/// the kind of strong aliasing guarantees an instance of `T` can expect: +/// the referent of the pointer should not be modified without a unique path to +/// its owning Unique. +/// +/// If you're uncertain of whether it's correct to use `Unique` for your purposes, +/// consider using `NonNull`, which has weaker semantics. +/// +/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer +/// is never dereferenced. This is so that enums may use this forbidden value +/// as a discriminant -- `Option>` has the same size as `Unique`. +/// However the pointer may still dangle if it isn't dereferenced. +/// +/// Unlike `*mut T`, `Unique` is covariant over `T`. This should always be correct +/// for any type which upholds Unique's aliasing requirements. +#[unstable(feature = "ptr_internals", issue = "0", + reason = "use NonNull instead and consider PhantomData \ + (if you also use #[may_dangle]), Send, and/or Sync")] +#[doc(hidden)] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(1)] +pub struct Unique { + pointer: *const T, + // NOTE: this marker has no consequences for variance, but is necessary + // for dropck to understand that we logically own a `T`. + // + // For details, see: + // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data + _marker: PhantomData, +} + +/// `Unique` pointers are `Send` if `T` is `Send` because the data they +/// reference is unaliased. Note that this aliasing invariant is +/// unenforced by the type system; the abstraction using the +/// `Unique` must enforce it. +#[unstable(feature = "ptr_internals", issue = "0")] +unsafe impl Send for Unique { } + +/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they +/// reference is unaliased. Note that this aliasing invariant is +/// unenforced by the type system; the abstraction using the +/// `Unique` must enforce it. +#[unstable(feature = "ptr_internals", issue = "0")] +unsafe impl Sync for Unique { } + +#[unstable(feature = "ptr_internals", issue = "0")] +impl Unique { + /// Creates a new `Unique` that is dangling, but well-aligned. + /// + /// This is useful for initializing types which lazily allocate, like + /// `Vec::new` does. + /// + /// Note that the pointer value may potentially represent a valid pointer to + /// a `T`, which means this must not be used as a "not yet initialized" + /// sentinel value. Types that lazily allocate must track initialization by + /// some other means. + // FIXME: rename to dangling() to match NonNull? + #[inline] + pub const fn empty() -> Self { + unsafe { + Unique::new_unchecked(mem::align_of::() as *mut T) + } + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl Unique { + /// Creates a new `Unique`. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[inline] + pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { + Unique { pointer: ptr as _, _marker: PhantomData } + } + + /// Creates a new `Unique` if `ptr` is non-null. + #[inline] + pub fn new(ptr: *mut T) -> Option { + if !ptr.is_null() { + Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }) + } else { + None + } + } + + /// Acquires the underlying `*mut` pointer. + #[inline] + pub const fn as_ptr(self) -> *mut T { + self.pointer as *mut T + } + + /// Dereferences the content. + /// + /// The resulting lifetime is bound to self so this behaves "as if" + /// it were actually an instance of T that is getting borrowed. If a longer + /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. + #[inline] + pub unsafe fn as_ref(&self) -> &T { + &*self.as_ptr() + } + + /// Mutably dereferences the content. + /// + /// The resulting lifetime is bound to self so this behaves "as if" + /// it were actually an instance of T that is getting borrowed. If a longer + /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + &mut *self.as_ptr() + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl Clone for Unique { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl Copy for Unique { } + +#[unstable(feature = "ptr_internals", issue = "0")] +impl CoerceUnsized> for Unique where T: Unsize { } + +#[unstable(feature = "ptr_internals", issue = "0")] +impl DispatchFromDyn> for Unique where T: Unsize { } + +#[unstable(feature = "ptr_internals", issue = "0")] +impl fmt::Debug for Unique { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl fmt::Pointer for Unique { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl From<&mut T> for Unique { + #[inline] + fn from(reference: &mut T) -> Self { + unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } } + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl From<&T> for Unique { + #[inline] + fn from(reference: &T) -> Self { + unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } } + } +} + +#[unstable(feature = "ptr_internals", issue = "0")] +impl<'a, T: ?Sized> From> for Unique { + #[inline] + fn from(p: NonNull) -> Self { + unsafe { Unique::new_unchecked(p.as_ptr()) } + } +} diff --git a/src/libcore/result.rs b/src/libcore/result.rs index bf8fd63b64..8a09877ce1 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -240,7 +240,7 @@ use crate::ops::{self, Deref}; /// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Err`]: enum.Result.html#variant.Err -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Result { @@ -1003,6 +1003,27 @@ fn unwrap_failed(msg: &str, error: E) -> ! { // Trait implementations ///////////////////////////////////////////////////////////////////////////// +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Result { + #[inline] + fn clone(&self) -> Self { + match self { + Ok(x) => Ok(x.clone()), + Err(x) => Err(x.clone()), + } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (Ok(to), Ok(from)) => to.clone_from(from), + (Err(to), Err(from)) => to.clone_from(from), + (to, from) => *to = from.clone(), + } + } +} + + #[stable(feature = "rust1", since = "1.0.0")] impl IntoIterator for Result { type Item = T; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 50d2ba0d3e..c6d44324ef 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -25,7 +25,7 @@ use crate::cmp::Ordering::{self, Less, Equal, Greater}; use crate::cmp; use crate::fmt; -use crate::intrinsics::assume; +use crate::intrinsics::{assume, exact_div, unchecked_sub}; use crate::isize; use crate::iter::*; use crate::ops::{FnMut, Try, self}; @@ -45,19 +45,6 @@ pub mod memchr; mod rotate; mod sort; -#[repr(C)] -union Repr<'a, T: 'a> { - rust: &'a [T], - rust_mut: &'a mut [T], - raw: FatPtr, -} - -#[repr(C)] -struct FatPtr { - data: *const T, - len: usize, -} - // // Extension traits // @@ -78,7 +65,7 @@ impl [T] { #[rustc_const_unstable(feature = "const_slice_len")] pub const fn len(&self) -> usize { unsafe { - Repr { rust: self }.raw.len + crate::ptr::Repr { rust: self }.raw.len } } @@ -2146,14 +2133,13 @@ impl [T] { /// Copying four bytes within a slice: /// /// ``` - /// # #![feature(copy_within)] /// let mut bytes = *b"Hello, World!"; /// /// bytes.copy_within(1..5, 8); /// /// assert_eq!(&bytes, b"Hello, Wello!"); /// ``` - #[unstable(feature = "copy_within", issue = "54236")] + #[stable(feature = "copy_within", since = "1.37.0")] pub fn copy_within>(&mut self, src: R, dest: usize) where T: Copy, @@ -2178,8 +2164,8 @@ impl [T] { assert!(dest <= self.len() - count, "dest is out of bounds"); unsafe { ptr::copy( - self.get_unchecked(src_start), - self.get_unchecked_mut(dest), + self.as_ptr().add(src_start), + self.as_mut_ptr().add(dest), count, ); } @@ -2999,14 +2985,27 @@ macro_rules! is_empty { // unexpected way. (Tested by `codegen/slice-position-bounds-check`.) macro_rules! len { ($self: ident) => {{ + #![allow(unused_unsafe)] // we're sometimes used within an unsafe block + let start = $self.ptr; - let diff = ($self.end as usize).wrapping_sub(start as usize); let size = size_from_ptr(start); if size == 0 { + // This _cannot_ use `unchecked_sub` because we depend on wrapping + // to represent the length of long ZST slice iterators. + let diff = ($self.end as usize).wrapping_sub(start as usize); diff } else { - // Using division instead of `offset_from` helps LLVM remove bounds checks - diff / size + // We know that `start <= end`, so can do better than `offset_from`, + // which needs to deal in signed. By setting appropriate flags here + // we can tell LLVM this, which helps it remove bounds checks. + // SAFETY: By the type invariant, `start <= end` + let diff = unsafe { unchecked_sub($self.end as usize, start as usize) }; + // By also telling LLVM that the pointers are apart by an exact + // multiple of the type size, it can optimize `len() == 0` down to + // `start == end` instead of `(end - start) < size`. + // SAFETY: By the type invariant, the pointers are aligned so the + // distance between them must be a multiple of pointee size + unsafe { exact_div(diff, size) } } }} } @@ -3020,6 +3019,28 @@ macro_rules! iterator { {$( $mut_:tt )*}, {$($extra:tt)*} ) => { + // Returns the first element and moves the start of the iterator forwards by 1. + // Greatly improves performance compared to an inlined function. The iterator + // must not be empty. + macro_rules! next_unchecked { + ($self: ident) => {& $( $mut_ )* *$self.post_inc_start(1)} + } + + // Returns the last element and moves the end of the iterator backwards by 1. + // Greatly improves performance compared to an inlined function. The iterator + // must not be empty. + macro_rules! next_back_unchecked { + ($self: ident) => {& $( $mut_ )* *$self.pre_dec_end(1)} + } + + // Shrinks the iterator when T is a ZST, by moving the end of the iterator + // backwards by `n`. `n` must not exceed `self.len()`. + macro_rules! zst_shrink { + ($self: ident, $n: ident) => { + $self.end = ($self.end as * $raw_mut u8).wrapping_offset(-$n) as * $raw_mut T; + } + } + impl<'a, T> $name<'a, T> { // Helper function for creating a slice from the iterator. #[inline(always)] @@ -3029,12 +3050,11 @@ macro_rules! iterator { // Helper function for moving the start of the iterator forwards by `offset` elements, // returning the old start. - // Unsafe because the offset must be in-bounds or one-past-the-end. + // Unsafe because the offset must not exceed `self.len()`. #[inline(always)] unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T { if mem::size_of::() == 0 { - // This is *reducing* the length. `ptr` never changes with ZST. - self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T; + zst_shrink!(self, offset); self.ptr } else { let old = self.ptr; @@ -3045,11 +3065,11 @@ macro_rules! iterator { // Helper function for moving the end of the iterator backwards by `offset` elements, // returning the new end. - // Unsafe because the offset must be in-bounds or one-past-the-end. + // Unsafe because the offset must not exceed `self.len()`. #[inline(always)] unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T { if mem::size_of::() == 0 { - self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T; + zst_shrink!(self, offset); self.ptr } else { self.end = self.end.offset(-offset); @@ -3086,7 +3106,7 @@ macro_rules! iterator { if is_empty!(self) { None } else { - Some(& $( $mut_ )* *self.post_inc_start(1)) + Some(next_unchecked!(self)) } } } @@ -3115,11 +3135,10 @@ macro_rules! iterator { } return None; } - // We are in bounds. `offset` does the right thing even for ZSTs. + // We are in bounds. `post_inc_start` does the right thing even for ZSTs. unsafe { - let elem = Some(& $( $mut_ )* *self.ptr.add(n)); - self.post_inc_start((n as isize).wrapping_add(1)); - elem + self.post_inc_start(n as isize); + Some(next_unchecked!(self)) } } @@ -3136,13 +3155,13 @@ macro_rules! iterator { let mut accum = init; unsafe { while len!(self) >= 4 { - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; + accum = f(accum, next_unchecked!(self))?; } while !is_empty!(self) { - accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; + accum = f(accum, next_unchecked!(self))?; } } Try::from_ok(accum) @@ -3213,11 +3232,25 @@ macro_rules! iterator { if is_empty!(self) { None } else { - Some(& $( $mut_ )* *self.pre_dec_end(1)) + Some(next_back_unchecked!(self)) } } } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<$elem> { + if n >= len!(self) { + // This iterator is now empty. + self.end = self.ptr; + return None; + } + // We are in bounds. `pre_dec_end` does the right thing even for ZSTs. + unsafe { + self.pre_dec_end(n as isize); + Some(next_back_unchecked!(self)) + } + } + #[inline] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try @@ -3226,14 +3259,14 @@ macro_rules! iterator { let mut accum = init; unsafe { while len!(self) >= 4 { - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; + accum = f(accum, next_back_unchecked!(self))?; } // inlining is_empty everywhere makes a huge performance difference while !is_empty!(self) { - accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; + accum = f(accum, next_back_unchecked!(self))?; } } Try::from_ok(accum) @@ -4158,6 +4191,24 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = match start.checked_add(self.chunk_size) { + Some(res) => cmp::min(res, self.v.len()), + None => self.v.len(), + }; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -4649,6 +4700,23 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { Some(fst) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -4774,6 +4842,24 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> { Some(head) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (_, nth_back) = tmp.split_at_mut(start); + self.v = tail; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -4898,6 +4984,24 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { Some(fst) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -5016,6 +5120,25 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> { Some(head) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (_, nth_back) = tmp.split_at_mut(start); + self.v = tail; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -5093,7 +5216,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); - Repr { raw: FatPtr { data, len } }.rust + &*ptr::slice_from_raw_parts(data, len) } /// Performs the same functionality as [`from_raw_parts`], except that a @@ -5114,7 +5237,7 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); - Repr { raw: FatPtr { data, len } }.rust_mut + &mut *ptr::slice_from_raw_parts_mut(data, len) } /// Converts a reference to T into a slice of length 1 (without copying). @@ -5330,7 +5453,7 @@ macro_rules! impl_marker_for { } impl_marker_for!(BytewiseEquality, - u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool); + u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize char bool); #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index ef4bd83cbc..34f2d8917e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -3971,6 +3971,16 @@ impl str { /// [`to_ascii_uppercase`]. /// /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("Grüße, Jürgen ❤"); + /// + /// s.make_ascii_uppercase(); + /// + /// assert_eq!("GRüßE, JüRGEN ❤", s); + /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] pub fn make_ascii_uppercase(&mut self) { let me = unsafe { self.as_bytes_mut() }; @@ -3986,6 +3996,16 @@ impl str { /// [`to_ascii_lowercase`]. /// /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("GRÜßE, JÜRGEN ❤"); + /// + /// s.make_ascii_lowercase(); + /// + /// assert_eq!("grÜße, jÜrgen ❤", s); + /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] pub fn make_ascii_lowercase(&mut self) { let me = unsafe { self.as_bytes_mut() }; diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 12414980d7..8dfb19fa03 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -1899,7 +1899,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i8", "../../../std/primitive.i8.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_min, atomic_max, 1, "AtomicI8::new(0)", @@ -1915,7 +1915,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u8", "../../../std/primitive.u8.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_umin, atomic_umax, 1, "AtomicU8::new(0)", @@ -1931,7 +1931,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i16", "../../../std/primitive.i16.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_min, atomic_max, 2, "AtomicI16::new(0)", @@ -1947,7 +1947,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u16", "../../../std/primitive.u16.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_umin, atomic_umax, 2, "AtomicU16::new(0)", @@ -1963,7 +1963,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i32", "../../../std/primitive.i32.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_min, atomic_max, 4, "AtomicI32::new(0)", @@ -1979,7 +1979,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u32", "../../../std/primitive.u32.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_umin, atomic_umax, 4, "AtomicU32::new(0)", @@ -1995,7 +1995,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i64", "../../../std/primitive.i64.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_min, atomic_max, 8, "AtomicI64::new(0)", @@ -2011,7 +2011,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u64", "../../../std/primitive.u64.html", - "#![feature(integer_atomics)]\n\n", + "", atomic_umin, atomic_umax, 8, "AtomicU64::new(0)", diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index a6d611d2e9..f1247239f4 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -147,14 +147,13 @@ impl RawWakerVTable { /// [`Waker`]: struct.Waker.html /// [`RawWaker`]: struct.RawWaker.html #[rustc_promotable] - #[cfg_attr(stage0, unstable(feature = "futures_api_const_fn_ptr", issue = "50547"))] - #[cfg_attr(not(stage0), stable(feature = "futures_api", since = "1.36.0"))] + #[stable(feature = "futures_api", since = "1.36.0")] // `rustc_allow_const_fn_ptr` is a hack that should not be used anywhere else // without first consulting with T-Lang. // // FIXME: remove whenever we have a stable way to accept fn pointers from const fn // (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062) - #[cfg_attr(not(stage0), rustc_allow_const_fn_ptr)] + #[rustc_allow_const_fn_ptr] pub const fn new( clone: unsafe fn(*const ()) -> RawWaker, wake: unsafe fn(*const ()), diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 7dfb1adad9..4d840ef24c 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1084,6 +1084,14 @@ fn test_iterator_sum_result() { assert_eq!(v.iter().cloned().sum::>(), Err(())); } +#[test] +fn test_iterator_sum_option() { + let v: &[Option] = &[Some(1), Some(2), Some(3), Some(4)]; + assert_eq!(v.iter().cloned().sum::>(), Some(10)); + let v: &[Option] = &[Some(1), None, Some(3), Some(4)]; + assert_eq!(v.iter().cloned().sum::>(), None); +} + #[test] fn test_iterator_product() { let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; @@ -1126,6 +1134,14 @@ impl Ord for Mod3 { } } +#[test] +fn test_iterator_product_option() { + let v: &[Option] = &[Some(1), Some(2), Some(3), Some(4)]; + assert_eq!(v.iter().cloned().product::>(), Some(24)); + let v: &[Option] = &[Some(1), None, Some(3), Some(4)]; + assert_eq!(v.iter().cloned().product::>(), None); +} + #[test] fn test_iterator_max() { let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; @@ -1641,6 +1657,23 @@ fn test_range_nth() { assert_eq!(r, 20..20); } +#[test] +fn test_range_nth_back() { + assert_eq!((10..15).nth_back(0), Some(14)); + assert_eq!((10..15).nth_back(1), Some(13)); + assert_eq!((10..15).nth_back(4), Some(10)); + assert_eq!((10..15).nth_back(5), None); + assert_eq!((-120..80_i8).nth_back(199), Some(-120)); + + let mut r = 10..20; + assert_eq!(r.nth_back(2), Some(17)); + assert_eq!(r, 10..17); + assert_eq!(r.nth_back(2), Some(14)); + assert_eq!(r, 10..14); + assert_eq!(r.nth_back(10), None); + assert_eq!(r, 10..10); +} + #[test] fn test_range_from_nth() { assert_eq!((10..).nth(0), Some(10)); @@ -1698,6 +1731,26 @@ fn test_range_inclusive_nth() { assert_eq!(ExactSizeIterator::is_empty(&r), true); } +#[test] +fn test_range_inclusive_nth_back() { + assert_eq!((10..=15).nth_back(0), Some(15)); + assert_eq!((10..=15).nth_back(1), Some(14)); + assert_eq!((10..=15).nth_back(5), Some(10)); + assert_eq!((10..=15).nth_back(6), None); + assert_eq!((-120..=80_i8).nth_back(200), Some(-120)); + + let mut r = 10_u8..=20; + assert_eq!(r.nth_back(2), Some(18)); + assert_eq!(r, 10..=17); + assert_eq!(r.nth_back(2), Some(15)); + assert_eq!(r, 10..=14); + assert_eq!(r.is_empty(), false); + assert_eq!(ExactSizeIterator::is_empty(&r), false); + assert_eq!(r.nth_back(10), None); + assert_eq!(r.is_empty(), true); + assert_eq!(ExactSizeIterator::is_empty(&r), true); +} + #[test] fn test_range_step() { #![allow(deprecated)] @@ -2280,6 +2333,40 @@ fn test_skip_try_folds() { assert_eq!(iter.next_back(), Some(24)); } +#[test] +fn test_skip_nth_back() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().skip(2); + assert_eq!(it.nth_back(0), Some(&5)); + assert_eq!(it.nth_back(1), Some(&3)); + assert_eq!(it.nth_back(0), Some(&2)); + assert_eq!(it.nth_back(0), None); + + let ys = [2, 3, 4, 5]; + let mut ity = ys.iter(); + let mut it = xs.iter().skip(2); + assert_eq!(it.nth_back(1), ity.nth_back(1)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + assert_eq!(it.nth_back(0), ity.nth_back(0)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + assert_eq!(it.nth_back(0), ity.nth_back(0)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + assert_eq!(it.nth_back(0), ity.nth_back(0)); + assert_eq!(it.clone().nth(0), ity.clone().nth(0)); + + let mut it = xs.iter().skip(2); + assert_eq!(it.nth_back(4), None); + assert_eq!(it.nth_back(0), None); + + let mut it = xs.iter(); + it.by_ref().skip(2).nth_back(3); + assert_eq!(it.next_back(), Some(&1)); + + let mut it = xs.iter(); + it.by_ref().skip(2).nth_back(10); + assert_eq!(it.next_back(), Some(&1)); +} + #[test] fn test_take_try_folds() { let f = &|acc, x| i32::checked_add(2*acc, x); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index c617596aba..bf072a9243 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -1,3 +1,4 @@ +#![feature(bound_cloned)] #![feature(box_syntax)] #![feature(cell_update)] #![feature(core_private_bignum)] @@ -10,7 +11,6 @@ #![feature(fmt_internals)] #![feature(hashmap_internals)] #![feature(is_sorted)] -#![feature(iter_nth_back)] #![feature(iter_once_with)] #![feature(pattern)] #![feature(range_is_empty)] @@ -25,11 +25,9 @@ #![feature(test)] #![feature(trusted_len)] #![feature(try_trait)] -#![feature(reverse_bits)] #![feature(inner_deref)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] -#![feature(copy_within)] #![feature(int_error_matching)] #![feature(const_fn)] #![warn(rust_2018_idioms)] diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index faeaabbf95..0e71426c64 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -31,6 +31,7 @@ fn ordinary() { test_literal!(0.1); test_literal!(12345.); test_literal!(0.9999999); + #[cfg(not(miri))] // Miri is too slow test_literal!(2.2250738585072014e-308); } @@ -77,6 +78,7 @@ fn zero() { test_literal!(0.0); test_literal!(1e-325); test_literal!(1e-326); + #[cfg(not(miri))] // Miri is too slow test_literal!(1e-500); } diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs index 78cf07119e..48755ae4c1 100644 --- a/src/libcore/tests/ops.rs +++ b/src/libcore/tests/ops.rs @@ -1,4 +1,4 @@ -use core::ops::{Range, RangeFull, RangeFrom, RangeTo, RangeInclusive}; +use core::ops::{Bound, Range, RangeFull, RangeFrom, RangeTo, RangeInclusive}; // Test the Range structs without the syntactic sugar. @@ -82,3 +82,18 @@ fn test_range_is_empty() { assert!( (NAN ..= EPSILON).is_empty()); assert!( (NAN ..= NAN).is_empty()); } + +#[test] +fn test_bound_cloned_unbounded() { + assert_eq!(Bound::<&u32>::Unbounded.cloned(), Bound::Unbounded); +} + +#[test] +fn test_bound_cloned_included() { + assert_eq!(Bound::Included(&3).cloned(), Bound::Included(3)); +} + +#[test] +fn test_bound_cloned_excluded() { + assert_eq!(Bound::Excluded(&3).cloned(), Bound::Excluded(3)); +} diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791..03e65d2fe0 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -88,6 +88,19 @@ fn test_iterator_nth() { assert_eq!(iter.nth(1).unwrap(), &v[4]); } +#[test] +fn test_iterator_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().nth_back(i).unwrap(), &v[v.len() - i - 1]); + } + assert_eq!(v.iter().nth_back(v.len()), None); + + let mut iter = v.iter(); + assert_eq!(iter.nth_back(2).unwrap(), &v[2]); + assert_eq!(iter.nth_back(1).unwrap(), &v[0]); +} + #[test] fn test_iterator_last() { let v: &[_] = &[0, 1, 2, 3, 4]; @@ -134,6 +147,30 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1, 2]); + assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); + + let v4: &[i32] = &[0, 1, 2]; + let mut c4 = v4.chunks(10); + assert_eq!(c4.nth_back(1_000_000_000usize), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; @@ -356,6 +393,19 @@ fn test_rchunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.rchunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]); + assert_eq!(c2.next_back(), None); +} + #[test] fn test_rchunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; @@ -407,6 +457,19 @@ fn test_rchunks_mut_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c2 = v2.rchunks_mut(3); + assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]); + assert_eq!(c2.next_back(), None); +} + #[test] fn test_rchunks_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; @@ -460,6 +523,19 @@ fn test_rchunks_exact_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_exact_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_exact(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6]; + let mut c2 = v2.rchunks_exact(3); + assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]); + assert_eq!(c2.next(), None); +} + #[test] fn test_rchunks_exact_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; @@ -518,6 +594,19 @@ fn test_rchunks_exact_mut_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_exact_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_exact_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6]; + let mut c2 = v2.rchunks_exact_mut(3); + assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]); + assert_eq!(c2.next(), None); +} + #[test] fn test_rchunks_exact_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; @@ -1436,6 +1525,13 @@ fn test_copy_within() { let mut bytes = *b"Hello, World!"; bytes.copy_within(.., 0); assert_eq!(&bytes, b"Hello, World!"); + + // Ensure that copying at the end of slice won't cause UB. + let mut bytes = *b"Hello, World!"; + bytes.copy_within(13..13, 5); + assert_eq!(&bytes, b"Hello, World!"); + bytes.copy_within(5..5, 13); + assert_eq!(&bytes, b"Hello, World!"); } #[test] @@ -1460,6 +1556,13 @@ fn test_copy_within_panics_src_inverted() { // 2 is greater than 1, so this range is invalid. bytes.copy_within(2..1, 0); } +#[test] +#[should_panic(expected = "attempted to index slice up to maximum usize")] +fn test_copy_within_panics_src_out_of_bounds() { + let mut bytes = *b"Hello, World!"; + // an inclusive range ending at usize::max_value() would make src_end overflow + bytes.copy_within(usize::max_value()..=usize::max_value(), 0); +} #[test] fn test_is_sorted() { diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml index 50779a2d9a..fc32f21ec4 100644 --- a/src/libfmt_macros/Cargo.toml +++ b/src/libfmt_macros/Cargo.toml @@ -8,3 +8,6 @@ edition = "2018" name = "fmt_macros" path = "lib.rs" crate-type = ["dylib"] + +[dependencies] +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 6fed830216..f6e9143dd0 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -10,6 +10,7 @@ #![deny(rust_2018_idioms)] #![deny(internal)] +#![deny(unused_lifetimes)] #![feature(nll)] #![feature(rustc_private)] @@ -24,6 +25,17 @@ use std::str; use std::string; use std::iter; +use syntax_pos::{InnerSpan, Symbol}; + +#[derive(Copy, Clone)] +struct InnerOffset(usize); + +impl InnerOffset { + fn to(self, end: InnerOffset) -> InnerSpan { + InnerSpan::new(self.0, end.0) + } +} + /// A piece is a portion of the format string which represents the next part /// to emit. These are emitted as a stream by the `Parser` class. #[derive(Copy, Clone, PartialEq)] @@ -39,7 +51,7 @@ pub enum Piece<'a> { #[derive(Copy, Clone, PartialEq)] pub struct Argument<'a> { /// Where to find this argument - pub position: Position<'a>, + pub position: Position, /// How to format the argument pub format: FormatSpec<'a>, } @@ -54,9 +66,9 @@ pub struct FormatSpec<'a> { /// Packed version of various flags provided pub flags: u32, /// The integer precision to use - pub precision: Count<'a>, + pub precision: Count, /// The string width requested for the resulting format - pub width: Count<'a>, + pub width: Count, /// The descriptor string representing the name of the format desired for /// this argument, this can be empty or any number of characters, although /// it is required to be one word. @@ -65,16 +77,16 @@ pub struct FormatSpec<'a> { /// Enum describing where an argument for a format can be located. #[derive(Copy, Clone, PartialEq)] -pub enum Position<'a> { +pub enum Position { /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), /// The argument is located at a specific index given in the format ArgumentIs(usize), /// The argument has a name. - ArgumentNamed(&'a str), + ArgumentNamed(Symbol), } -impl Position<'_> { +impl Position { pub fn index(&self) -> Option { match self { ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i), @@ -119,11 +131,11 @@ pub enum Flag { /// A count is used for the precision and width parameters of an integer, and /// can reference either an argument or a literal integer. #[derive(Copy, Clone, PartialEq)] -pub enum Count<'a> { +pub enum Count { /// The count is specified explicitly. CountIs(usize), /// The count is specified by the argument with the given name. - CountIsName(&'a str), + CountIsName(Symbol), /// The count is specified by the argument at the given index. CountIsParam(usize), /// The count is implied and cannot be explicitly specified. @@ -134,9 +146,8 @@ pub struct ParseError { pub description: string::String, pub note: Option, pub label: string::String, - pub start: SpanIndex, - pub end: SpanIndex, - pub secondary_label: Option<(string::String, SpanIndex, SpanIndex)>, + pub span: InnerSpan, + pub secondary_label: Option<(string::String, InnerSpan)>, } /// The parser structure for interpreting the input format string. This is @@ -155,24 +166,15 @@ pub struct Parser<'a> { /// `Some(raw count)` when the string is "raw", used to position spans correctly style: Option, /// Start and end byte offset of every successfully parsed argument - pub arg_places: Vec<(SpanIndex, SpanIndex)>, + pub arg_places: Vec, /// Characters that need to be shifted skips: Vec, - /// Span offset of the last opening brace seen, used for error reporting - last_opening_brace_pos: Option, + /// Span of the last opening brace seen, used for error reporting + last_opening_brace: Option, /// Wether the source string is comes from `println!` as opposed to `format!` or `print!` append_newline: bool, } -#[derive(Clone, Copy, Debug)] -pub struct SpanIndex(pub usize); - -impl SpanIndex { - pub fn unwrap(self) -> usize { - self.0 - } -} - impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; @@ -180,19 +182,20 @@ impl<'a> Iterator for Parser<'a> { if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { - let curr_last_brace = self.last_opening_brace_pos; - self.last_opening_brace_pos = Some(self.to_span_index(pos)); + let curr_last_brace = self.last_opening_brace; + let byte_pos = self.to_span_index(pos); + self.last_opening_brace = Some(byte_pos.to(InnerOffset(byte_pos.0 + 1))); self.cur.next(); if self.consume('{') { - self.last_opening_brace_pos = curr_last_brace; + self.last_opening_brace = curr_last_brace; Some(String(self.string(pos + 1))) } else { let arg = self.argument(); - if let Some(arg_pos) = self.must_consume('}').map(|end| { - (self.to_span_index(pos), self.to_span_index(end + 1)) - }) { - self.arg_places.push(arg_pos); + if let Some(end) = self.must_consume('}') { + let start = self.to_span_index(pos); + let end = self.to_span_index(end + 1); + self.arg_places.push(start.to(end)); } Some(NextArgument(arg)) } @@ -207,8 +210,7 @@ impl<'a> Iterator for Parser<'a> { "unmatched `}` found", "unmatched `}`", "if you intended to print `}`, you can escape it using `}}`", - err_pos, - err_pos, + err_pos.to(err_pos), ); None } @@ -240,7 +242,7 @@ impl<'a> Parser<'a> { style, arg_places: vec![], skips, - last_opening_brace_pos: None, + last_opening_brace: None, append_newline, } } @@ -252,15 +254,13 @@ impl<'a> Parser<'a> { &mut self, description: S1, label: S2, - start: SpanIndex, - end: SpanIndex, + span: InnerSpan, ) { self.errors.push(ParseError { description: description.into(), note: None, label: label.into(), - start, - end, + span, secondary_label: None, }); } @@ -273,15 +273,13 @@ impl<'a> Parser<'a> { description: S1, label: S2, note: S3, - start: SpanIndex, - end: SpanIndex, + span: InnerSpan, ) { self.errors.push(ParseError { description: description.into(), note: Some(note.into()), label: label.into(), - start, - end, + span, secondary_label: None, }); } @@ -302,22 +300,21 @@ impl<'a> Parser<'a> { } } - fn raw(&self) -> usize { - self.style.map(|raw| raw + 1).unwrap_or(0) - } - - fn to_span_index(&self, pos: usize) -> SpanIndex { + fn to_span_index(&self, pos: usize) -> InnerOffset { let mut pos = pos; + // This handles the raw string case, the raw argument is the number of # + // in r###"..."### (we need to add one because of the `r`). + let raw = self.style.map(|raw| raw + 1).unwrap_or(0); for skip in &self.skips { if pos > *skip { pos += 1; - } else if pos == *skip && self.raw() == 0 { + } else if pos == *skip && raw == 0 { pos += 1; } else { break; } } - SpanIndex(self.raw() + pos + 1) + InnerOffset(raw + pos + 1) } /// Forces consumption of the specified character. If the character is not @@ -335,8 +332,8 @@ impl<'a> Parser<'a> { let label = "expected `}`".to_owned(); let (note, secondary_label) = if c == '}' { (Some("if you intended to print `{`, you can escape it using `{{`".to_owned()), - self.last_opening_brace_pos.map(|pos| { - ("because of this opening brace".to_owned(), pos, pos) + self.last_opening_brace.map(|sp| { + ("because of this opening brace".to_owned(), sp) })) } else { (None, None) @@ -345,8 +342,7 @@ impl<'a> Parser<'a> { description, note, label, - start: pos, - end: pos, + span: pos.to(pos), secondary_label, }); None @@ -360,8 +356,8 @@ impl<'a> Parser<'a> { let label = format!("expected `{:?}`", c); let (note, secondary_label) = if c == '}' { (Some("if you intended to print `{`, you can escape it using `{{`".to_owned()), - self.last_opening_brace_pos.map(|pos| { - ("because of this opening brace".to_owned(), pos, pos) + self.last_opening_brace.map(|sp| { + ("because of this opening brace".to_owned(), sp) })) } else { (None, None) @@ -370,12 +366,11 @@ impl<'a> Parser<'a> { description, note, label, - start: pos, - end: pos, + span: pos.to(pos), secondary_label, }); } else { - self.err(description, format!("expected `{:?}`", c), pos, pos); + self.err(description, format!("expected `{:?}`", c), pos.to(pos)); } None } @@ -434,20 +429,24 @@ impl<'a> Parser<'a> { /// integer index of an argument, a named argument, or a blank string. /// Returns `Some(parsed_position)` if the position is not implicitly /// consuming a macro argument, `None` if it's the case. - fn position(&mut self) -> Option> { + fn position(&mut self) -> Option { if let Some(i) = self.integer() { Some(ArgumentIs(i)) } else { match self.cur.peek() { - Some(&(_, c)) if c.is_alphabetic() => Some(ArgumentNamed(self.word())), + Some(&(_, c)) if c.is_alphabetic() => { + Some(ArgumentNamed(Symbol::intern(self.word()))) + } Some(&(pos, c)) if c == '_' => { let invalid_name = self.string(pos); self.err_with_note(format!("invalid argument name `{}`", invalid_name), "invalid argument name", "argument names cannot start with an underscore", - self.to_span_index(pos), - self.to_span_index(pos + invalid_name.len())); - Some(ArgumentNamed(invalid_name)) + self.to_span_index(pos).to( + self.to_span_index(pos + invalid_name.len()) + ), + ); + Some(ArgumentNamed(Symbol::intern(invalid_name))) }, // This is an `ArgumentNext`. @@ -555,7 +554,7 @@ impl<'a> Parser<'a> { /// Parses a Count parameter at the current position. This does not check /// for 'CountIsNextParam' because that is only used in precision, not /// width. - fn count(&mut self) -> Count<'a> { + fn count(&mut self) -> Count { if let Some(i) = self.integer() { if self.consume('$') { CountIsParam(i) @@ -569,7 +568,7 @@ impl<'a> Parser<'a> { self.cur = tmp; CountImplied } else if self.consume('$') { - CountIsName(word) + CountIsName(Symbol::intern(word)) } else { self.cur = tmp; CountImplied @@ -623,245 +622,4 @@ impl<'a> Parser<'a> { } #[cfg(test)] -mod tests { - use super::*; - - fn same(fmt: &'static str, p: &[Piece<'static>]) { - let parser = Parser::new(fmt, None, vec![], false); - assert!(parser.collect::>>() == p); - } - - fn fmtdflt() -> FormatSpec<'static> { - return FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }; - } - - fn musterr(s: &str) { - let mut p = Parser::new(s, None, vec![], false); - p.next(); - assert!(!p.errors.is_empty()); - } - - #[test] - fn simple() { - same("asdf", &[String("asdf")]); - same("a{{b", &[String("a"), String("{b")]); - same("a}}b", &[String("a"), String("}b")]); - same("a}}", &[String("a"), String("}")]); - same("}}", &[String("}")]); - same("\\}}", &[String("\\"), String("}")]); - } - - #[test] - fn invalid01() { - musterr("{") - } - #[test] - fn invalid02() { - musterr("}") - } - #[test] - fn invalid04() { - musterr("{3a}") - } - #[test] - fn invalid05() { - musterr("{:|}") - } - #[test] - fn invalid06() { - musterr("{:>>>}") - } - - #[test] - fn format_nothing() { - same("{}", - &[NextArgument(Argument { - position: ArgumentImplicitlyIs(0), - format: fmtdflt(), - })]); - } - #[test] - fn format_position() { - same("{3}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: fmtdflt(), - })]); - } - #[test] - fn format_position_nothing_else() { - same("{3:}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: fmtdflt(), - })]); - } - #[test] - fn format_type() { - same("{3:a}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "a", - }, - })]); - } - #[test] - fn format_align_fill() { - same("{3:>}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: None, - align: AlignRight, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - same("{3:0<}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: Some('0'), - align: AlignLeft, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - same("{3:*]) { + let parser = Parser::new(fmt, None, vec![], false); + assert!(parser.collect::>>() == p); +} + +fn fmtdflt() -> FormatSpec<'static> { + return FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "", + }; +} + +fn musterr(s: &str) { + let mut p = Parser::new(s, None, vec![], false); + p.next(); + assert!(!p.errors.is_empty()); +} + +#[test] +fn simple() { + same("asdf", &[String("asdf")]); + same("a{{b", &[String("a"), String("{b")]); + same("a}}b", &[String("a"), String("}b")]); + same("a}}", &[String("a"), String("}")]); + same("}}", &[String("}")]); + same("\\}}", &[String("\\"), String("}")]); +} + +#[test] +fn invalid01() { + musterr("{") +} +#[test] +fn invalid02() { + musterr("}") +} +#[test] +fn invalid04() { + musterr("{3a}") +} +#[test] +fn invalid05() { + musterr("{:|}") +} +#[test] +fn invalid06() { + musterr("{:>>>}") +} + +#[test] +fn format_nothing() { + same("{}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + format: fmtdflt(), + })]); +} +#[test] +fn format_position() { + same("{3}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: fmtdflt(), + })]); +} +#[test] +fn format_position_nothing_else() { + same("{3:}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: fmtdflt(), + })]); +} +#[test] +fn format_type() { + same("{3:a}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "a", + }, + })]); +} +#[test] +fn format_align_fill() { + same("{3:>}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: None, + align: AlignRight, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "", + }, + })]); + same("{3:0<}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: Some('0'), + align: AlignLeft, + flags: 0, + precision: CountImplied, + width: CountImplied, + ty: "", + }, + })]); + same("{3:*(g: &'a G, } #[cfg(test)] -mod tests { - use NodeLabels::*; - use super::{Id, Labeller, Nodes, Edges, GraphWalk, render, Style}; - use super::LabelText::{self, LabelStr, EscStr, HtmlStr}; - use std::io; - use std::io::prelude::*; - - /// each node is an index in a vector in the graph. - type Node = usize; - struct Edge { - from: usize, - to: usize, - label: &'static str, - style: Style, - } - - fn edge(from: usize, to: usize, label: &'static str, style: Style) -> Edge { - Edge { - from, - to, - label, - style, - } - } - - struct LabelledGraph { - /// The name for this graph. Used for labeling generated `digraph`. - name: &'static str, - - /// Each node is an index into `node_labels`; these labels are - /// used as the label text for each node. (The node *names*, - /// which are unique identifiers, are derived from their index - /// in this array.) - /// - /// If a node maps to None here, then just use its name as its - /// text. - node_labels: Vec>, - - node_styles: VecHTML here"; /// let output = "Some HTML here"; /// /// let document = Builder::new() @@ -1531,7 +1756,7 @@ impl Document { pub fn to_string(&self) -> String { let opts = Self::serialize_opts(); let mut ret_val = Vec::new(); - serialize(&mut ret_val, &self.0, opts) + serialize(&mut ret_val, &self.0.document.children.borrow()[0], opts) .expect("Writing to a string shouldn't fail (expect on OOM)"); String::from_utf8(ret_val) .expect("html5ever only supports UTF8") @@ -1552,7 +1777,7 @@ impl Document { /// /// use ammonia::Builder; /// - /// let input = "Some HTML here"; /// let expected = b"Some HTML here"; /// /// let document = Builder::new() @@ -1567,7 +1792,7 @@ impl Document { W: io::Write, { let opts = Self::serialize_opts(); - serialize(writer, &self.0, opts) + serialize(writer, &self.0.document.children.borrow()[0], opts) } /// Exposes the `Document` instance as an [`html5ever::rcdom::Handle`][h]. @@ -1631,7 +1856,7 @@ impl Document { /// # fn main() { do_main().unwrap() } #[cfg(ammonia_unstable)] pub fn to_dom_node(&self) -> Handle { - self.0.clone() + self.0.document.children.borrow()[0].clone() } fn serialize_opts() -> SerializeOpts { @@ -1639,8 +1864,22 @@ impl Document { } } +impl Clone for Document { + fn clone(&self) -> Self { + let parser = Builder::make_parser(); + let dom = parser.one(&self.to_string()[..]); + Document(dom) + } +} + +impl fmt::Display for Document { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_string()) + } +} + impl fmt::Debug for Document { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Document({})", self.to_string()) } } @@ -1655,6 +1894,18 @@ impl From for String { mod test { use super::*; #[test] + fn deeply_nested_whitelisted() { + clean(&"".repeat(60_000)); + } + #[test] + fn deeply_nested_blacklisted() { + clean(&"".repeat(60_000)); + } + #[test] + fn deeply_nested_alternating() { + clean(&"".repeat(35_000)); + } + #[test] fn included_angles() { let fragment = "1 < 2"; let result = clean(fragment); @@ -1664,7 +1915,7 @@ mod test { fn remove_script() { let fragment = "an example"; let result = clean(fragment); - assert_eq!(result, "an evil() example"); + assert_eq!(result, "an example"); } #[test] fn ignore_link() { @@ -1719,6 +1970,89 @@ mod test { "Test" ); } + #[test] + fn attribute_filter_nop() { + let fragment = "Test"; + let result = Builder::new() + .attribute_filter(|elem, attr, value| { + assert_eq!("a", elem); + assert!(match (attr, value) { + ("href", "test") => true, + ("rel", "noopener noreferrer") => true, + _ => false, + }, value.to_string()); + Some(value.into()) + }) + .clean(fragment) + .to_string(); + assert_eq!( + result, + "Test" + ); + } + + #[test] + fn attribute_filter_drop() { + let fragment = "Testtest"; + let result = Builder::new() + .attribute_filter(|elem, attr, value| { + assert_eq!("img", elem); + match (attr, value) { + ("src", "imgtest") => None, + ("alt", "test") => Some(value.into()), + _ => panic!("unexpected"), + } + }) + .clean(fragment) + .to_string(); + assert_eq!( + result, + r#"Testtest"# + ); + } + + #[test] + fn url_filter_absolute() { + let fragment = "Testtest"; + let result = Builder::new() + .attribute_filter(|elem, attr, value| { + assert_eq!("img", elem); + match (attr, value) { + ("src", "imgtest") => Some(format!("https://example.com/images/{}", value).into()), + ("alt", "test") => None, + _ => panic!("unexpected"), + } + }) + .url_relative(UrlRelative::RewriteWithBase(Url::parse("http://wrong.invalid/").unwrap())) + .clean(fragment) + .to_string(); + assert_eq!( + result, + r#"Test"# + ); + } + + #[test] + fn url_filter_relative() { + let fragment = "Testtest"; + let result = Builder::new() + .attribute_filter(|elem, attr, value| { + assert_eq!("img", elem); + match (attr, value) { + ("src", "imgtest") => Some("rewrite".into()), + ("alt", "test") => Some("altalt".into()), + _ => panic!("unexpected"), + } + }) + .url_relative(UrlRelative::RewriteWithBase(Url::parse("https://example.com/base/#").unwrap())) + .clean(fragment) + .to_string(); + assert_eq!( + result, + r#"Testaltalt"# + ); + } + #[test] fn rewrite_url_relative_no_rel() { let fragment = "Test"; @@ -1899,6 +2233,61 @@ mod test { ); } #[test] + fn remove_non_allowed_attributes_with_tag_attribute_values() { + let fragment = "

"; + let result = Builder::new() + .tag_attribute_values(hashmap![ + "p" => hashmap![ + "data-label" => hashset!["bar"], + ], + ]) + .tag_attributes(hashmap![ + "p" => hashset!["name"], + ]) + .clean(fragment); + assert_eq!( + result.to_string(), + "

", + ); + } + #[test] + fn keep_allowed_attributes_with_tag_attribute_values() { + let fragment = "

"; + let result = Builder::new() + .tag_attribute_values(hashmap![ + "p" => hashmap![ + "data-label" => hashset!["bar"], + ], + ]) + .tag_attributes(hashmap![ + "p" => hashset!["name"], + ]) + .clean(fragment); + assert_eq!( + result.to_string(), + "

", + ); + } + #[test] + fn tag_attribute_values_case_insensitive() { + let fragment = ""; + let result = Builder::new() + .tags(hashset!["input"]) + .tag_attribute_values(hashmap![ + "input" => hashmap![ + "type" => hashset!["checkbox"], + ], + ]) + .tag_attributes(hashmap![ + "input" => hashset!["name"], + ]) + .clean(fragment); + assert_eq!( + result.to_string(), + "", + ); + } + #[test] fn remove_entity_link() { let fragment = "Click me!"; @@ -1985,7 +2374,7 @@ mod test { let fragment = b"an example"; let result = Builder::new().clean_from_reader(&fragment[..]); assert!(result.is_ok()); - assert_eq!(result.unwrap().to_string(), "an evil() example"); + assert_eq!(result.unwrap().to_string(), "an example"); } #[test] fn reader_non_utf8() { @@ -1995,6 +2384,12 @@ mod test { assert_eq!(result.unwrap().to_string(), "non-utf8 \u{fffd}string"); } #[test] + fn display_impl() { + let fragment = r#"a link"#; + let result = Builder::new().link_rel(None).clean(fragment); + assert_eq!(format!("{}", result), "a link"); + } + #[test] fn debug_impl() { let fragment = r#"a link"#; let result = Builder::new().link_rel(None).clean(fragment); diff --git a/vendor/annotate-snippets/.cargo-checksum.json b/vendor/annotate-snippets/.cargo-checksum.json new file mode 100644 index 0000000000..caa39926e0 --- /dev/null +++ b/vendor/annotate-snippets/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"925115cdc75915ab34fdb56d61c6b98fd187e10ea7539f5f3cfaafb17c5d6d70","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-MIT":"49c0b000c03731d9e3970dc059ad4ca345d773681f4a612b0024435b663e0220","README.md":"bb23326d42384b69634860bd4f5bffd42480834227d3e5e722c3604e887a75e7","examples/expected_type.rs":"e49f9628c7c14c08d9c3c8286e4020494db2c166c5d3b21c30209a98a7888ad2","examples/footer.rs":"031aee0dba4cbc0a9c5ca4e6342976c4a6c9e9945e626dff54ef525f6a37ff4a","examples/format.rs":"634576d4943b41b30a0b815dbb308ea162e7f4be1e7c2d9595f6cf1f6f59a2e2","examples/multislice.rs":"228063f631a9dcad72c37324d9f669c60181fd1177186965563710cf3bddbe82","src/display_list/from_snippet.rs":"354ed2170db40e8324d3e2c28fe938623b45e4993d6124d3d4979a1546664d09","src/display_list/mod.rs":"e1810ba12bf48515d063075b9cdda3ede667d58bb33e75b1de27c392fbe11836","src/display_list/structs.rs":"ac17f7b364829fcf1336466d6937f31a14c7e8c46a8a8962bc1f8a1c2eb2317f","src/formatter/mod.rs":"12304e8d46260e155368987bacac30b717c688f9dae2e0961025b3cd3a49f76b","src/formatter/style.rs":"185d5b481ba2052da55de712735bf1d50d621477ca08b339cfae49b3c794325f","src/lib.rs":"98848cedd3dd581ea1b7a8443607af4a51a7c4fe27828cd3ebff9140a3ff5a76","src/snippet.rs":"904d642357a4ed5d2a0387e7e9253ec4631ef852c7188507f98e474b16fd5adf","src/stylesheets/color.rs":"fbca2562b765bb5710c0934dcc0a56a349622b2936ddc4b2bbd2e92ebc875933","src/stylesheets/mod.rs":"ef8038360631561f53a4472cffe45e1fbde04f4aed8d4738426da88214b94576","src/stylesheets/no_color.rs":"fc61040fd8a2be45468ff7594a8f74674853867fb3afc81ec24f383c165b22ba","tests/diff/mod.rs":"d423c84a84a4f3247703edf9b5d85b1e6d06f279539af676505abbcc5e2484fb","tests/dl_from_snippet.rs":"4074b10037c66fe15d813a9b80e2842ccdb7520afb04b28e83e4425baefb4d9b","tests/fixtures.rs":"4047554b1b9840437d4779d4689704b792b0cf07173f3fda92e17b4301e23aa0","tests/fixtures/no-color/multiline_annotation.txt":"b8d36204f260d91e99672fe11839e1fe416f6a18b6de46c923d43c0430a97ee7","tests/fixtures/no-color/multiline_annotation.yaml":"fab49391fa0c53ffe3b997f70c5615c0b767c21de105b0a3805a692085e641ae","tests/fixtures/no-color/multiline_annotation2.txt":"391da0ef9bec5de45a30a0869ecc3227a1d3272872508af1d7a294fa431c8dd2","tests/fixtures/no-color/multiline_annotation2.yaml":"aa2fb2c8666f1c625c92dd1630dd643ba304617334c077b169e5a27be0c116af","tests/fixtures/no-color/multiple_annotations.txt":"b284ab83d9de3aa9d014d3d04ac199517967885bc064f0462c15d6a4d71554aa","tests/fixtures/no-color/multiple_annotations.yaml":"7892a2eb95a0442e3926c31482202410d867a87ef3d35c6c4599ebd6e5c33d31","tests/fixtures/no-color/simple.txt":"cb9b7fab003c58e03ce87cae4fd04a40983ff3f8ee329b494dcb3abcf576fccd","tests/fixtures/no-color/simple.yaml":"9650f0a4ff157c7daf6cc3fc33179173f1cd4c1ace298501efca3da134aec1e9","tests/formatter.rs":"adbe7cd1361af4bc1a57648833cf279c255aeda05293ed8f7774f9013db5ea6b","tests/snippet/mod.rs":"0dc871f3d7d49564ae0d355eb70319973b4f88f69c2e3759e184dba4d7118c47"},"package":"e8bcdcd5b291ce85a78f2b9d082a8de9676c12b1840d386d67bc5eea6f9d2b4e"} \ No newline at end of file diff --git a/vendor/annotate-snippets/Cargo.toml b/vendor/annotate-snippets/Cargo.toml new file mode 100644 index 0000000000..915f4d7dc9 --- /dev/null +++ b/vendor/annotate-snippets/Cargo.toml @@ -0,0 +1,57 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "annotate-snippets" +version = "0.5.0" +authors = ["Zibi Braniecki "] +description = "Library for building code annotations" +readme = "README.md" +keywords = ["code", "analysis", "ascii", "errors", "debug"] +license = "Apache-2.0/MIT" +repository = "https://github.com/zbraniecki/annotate-snippets-rs" +[dependencies.ansi_term] +version = "0.11.0" +optional = true +[dev-dependencies.ansi_term] +version = "^0.11" + +[dev-dependencies.difference] +version = "^2.0" + +[dev-dependencies.glob] +version = "^0.2" + +[dev-dependencies.serde] +version = "^1.0" + +[dev-dependencies.serde_derive] +version = "^1.0" + +[dev-dependencies.serde_yaml] +version = "^0.8" + +[features] +color = ["ansi_term"] +default = [] +[badges.coveralls] +branch = "master" +repository = "zbraniecki/annotate-snippets-rs" +service = "github" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "zbraniecki/annotate-snippets-rs" diff --git a/vendor/unreachable/LICENSE-APACHE b/vendor/annotate-snippets/LICENSE-APACHE similarity index 99% rename from vendor/unreachable/LICENSE-APACHE rename to vendor/annotate-snippets/LICENSE-APACHE index 8f71f43fee..261eeb9e9f 100644 --- a/vendor/unreachable/LICENSE-APACHE +++ b/vendor/annotate-snippets/LICENSE-APACHE @@ -178,7 +178,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -199,4 +199,3 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - diff --git a/vendor/annotate-snippets/LICENSE-MIT b/vendor/annotate-snippets/LICENSE-MIT new file mode 100644 index 0000000000..5655fa311c --- /dev/null +++ b/vendor/annotate-snippets/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright 2017 Mozilla + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/annotate-snippets/README.md b/vendor/annotate-snippets/README.md new file mode 100644 index 0000000000..44c8a62d4b --- /dev/null +++ b/vendor/annotate-snippets/README.md @@ -0,0 +1,99 @@ +# annotate-snippets + +`annotate-snippets` is a Rust library for annotation of programming code slices. + +[![crates.io](http://meritbadge.herokuapp.com/annotate-snippets)](https://crates.io/crates/annotate-snippets) +[![Build Status](https://travis-ci.org/zbraniecki/annotate-snippets-rs.svg?branch=master)](https://travis-ci.org/zbraniecki/annotate-snippets-rs) +[![Coverage Status](https://coveralls.io/repos/github/zbraniecki/annotate-snippets-rs/badge.svg?branch=master)](https://coveralls.io/github/zbraniecki/annotate-snippets-rs?branch=master) + +The library helps visualize meta information annotating source code slices. +It takes a data structure called `Snippet` on the input and procudes a `String` +which may look like this: + +```text +error[E0308]: mismatched types + --> src/format.rs:52:1 + | +51 | ) -> Option { + | -------------- expected `Option` because of return type +52 | / for ann in annotations { +53 | | match (ann.range.0, ann.range.1) { +54 | | (None, None) => continue, +55 | | (Some(start), Some(end)) if start > end_index => continue, +... | +71 | | } +72 | | } + | |_____^ expected enum `std::option::Option`, found () +``` + +[Documentation][] + +[Documentation]: https://docs.rs/annotate-snippets/ + +Installation +------------ + +```toml +[dependencies] +annotate-snippets-rs = "0.1.0" +``` + + +Usage +----- + +```rust +extern crate annotate_snippets; + +use annotate_snippets::snippet; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("expected type, found `22`".to_string()), + id: None, + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![ + Slice { + source: r#" +This is an example +content of the slice +which will be annotated +with the list of annotations below. + "#.to_string(), + line_start: 26, + origin: Some("examples/example.txt".to_string()), + fold: false, + annotations: vec![ + SourceAnnotation { + label: "Example error annotation".to_string(), + annotation_type: AnnotationType::Error, + range: (13, 18), + }, + SourceAnnotation { + label: "and here's a warning".to_string(), + annotation_type: AnnotationType::Warning, + range: (34, 50), + }, + ], + }, + ], + }; + + let dl = DisplayList::from(snippet); + let dlf = DisplayListFormatter::new(true); + dlf.format(&dl); +} +``` + +Local Development +----------------- + + cargo build + cargo test + +When submitting a PR please use [`cargo fmt`][] (nightly). + +[`cargo fmt`]: https://github.com/rust-lang-nursery/rustfmt diff --git a/vendor/annotate-snippets/examples/expected_type.rs b/vendor/annotate-snippets/examples/expected_type.rs new file mode 100644 index 0000000000..6c6ed0127b --- /dev/null +++ b/vendor/annotate-snippets/examples/expected_type.rs @@ -0,0 +1,42 @@ +extern crate annotate_snippets; + +use annotate_snippets::display_list::DisplayList; +use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("expected type, found `22`".to_string()), + id: None, + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![Slice { + source: r#" annotations: vec![SourceAnnotation { + label: "expected struct `annotate_snippets::snippet::Slice`, found reference" + .to_string(), + range: <22, 25>,"# + .to_string(), + line_start: 26, + origin: Some("examples/footer.rs".to_string()), + fold: true, + annotations: vec![ + SourceAnnotation { + label: "".to_string(), + annotation_type: AnnotationType::Error, + range: (208, 210), + }, + SourceAnnotation { + label: "while parsing this struct".to_string(), + annotation_type: AnnotationType::Info, + range: (34, 50), + }, + ], + }], + }; + + let dl = DisplayList::from(snippet); + let dlf = DisplayListFormatter::new(true); + println!("{}", dlf.format(&dl)); +} diff --git a/vendor/annotate-snippets/examples/footer.rs b/vendor/annotate-snippets/examples/footer.rs new file mode 100644 index 0000000000..7cbc9496ca --- /dev/null +++ b/vendor/annotate-snippets/examples/footer.rs @@ -0,0 +1,39 @@ +extern crate annotate_snippets; + +use annotate_snippets::display_list::DisplayList; +use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("mismatched types".to_string()), + id: Some("E0308".to_string()), + annotation_type: AnnotationType::Error, + }), + footer: vec![Annotation { + label: Some( + "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`" + .to_string(), + ), + id: None, + annotation_type: AnnotationType::Note, + }], + slices: vec![Slice { + source: " slices: vec![\"A\",".to_string(), + line_start: 13, + origin: Some("src/multislice.rs".to_string()), + fold: false, + annotations: vec![SourceAnnotation { + label: "expected struct `annotate_snippets::snippet::Slice`, found reference" + .to_string(), + range: (21, 24), + annotation_type: AnnotationType::Error, + }], + }], + }; + + let dl = DisplayList::from(snippet); + let dlf = DisplayListFormatter::new(true); + println!("{}", dlf.format(&dl)); +} diff --git a/vendor/annotate-snippets/examples/format.rs b/vendor/annotate-snippets/examples/format.rs new file mode 100644 index 0000000000..30d86b5c34 --- /dev/null +++ b/vendor/annotate-snippets/examples/format.rs @@ -0,0 +1,60 @@ +extern crate annotate_snippets; + +use annotate_snippets::display_list::DisplayList; +use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; + +fn main() { + let snippet = Snippet { + slices: vec![Slice { + source: r#") -> Option { + for ann in annotations { + match (ann.range.0, ann.range.1) { + (None, None) => continue, + (Some(start), Some(end)) if start > end_index => continue, + (Some(start), Some(end)) if start >= start_index => { + let label = if let Some(ref label) = ann.label { + format!(" {}", label) + } else { + String::from("") + }; + + return Some(format!( + "{}{}{}", + " ".repeat(start - start_index), + "^".repeat(end - start), + label + )); + } + _ => continue, + } + }"# + .to_string(), + line_start: 51, + origin: Some("src/format.rs".to_string()), + fold: false, + annotations: vec![ + SourceAnnotation { + label: "expected `Option` because of return type".to_string(), + annotation_type: AnnotationType::Warning, + range: (5, 19), + }, + SourceAnnotation { + label: "expected enum `std::option::Option`".to_string(), + annotation_type: AnnotationType::Error, + range: (23, 745), + }, + ], + }], + title: Some(Annotation { + label: Some("mismatched types".to_string()), + id: Some("E0308".to_string()), + annotation_type: AnnotationType::Error, + }), + footer: vec![], + }; + + let dl = DisplayList::from(snippet); + let dlf = DisplayListFormatter::new(true); + println!("{}", dlf.format(&dl)); +} diff --git a/vendor/annotate-snippets/examples/multislice.rs b/vendor/annotate-snippets/examples/multislice.rs new file mode 100644 index 0000000000..e1f294645a --- /dev/null +++ b/vendor/annotate-snippets/examples/multislice.rs @@ -0,0 +1,36 @@ +extern crate annotate_snippets; + +use annotate_snippets::display_list::DisplayList; +use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet}; + +fn main() { + let snippet = Snippet { + title: Some(Annotation { + label: Some("mismatched types".to_string()), + id: None, + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![ + Slice { + source: "Foo".to_string(), + line_start: 51, + origin: Some("src/format.rs".to_string()), + fold: false, + annotations: vec![], + }, + Slice { + source: "Faa".to_string(), + line_start: 129, + origin: Some("src/display.rs".to_string()), + fold: false, + annotations: vec![], + }, + ], + }; + + let dl = DisplayList::from(snippet); + let dlf = DisplayListFormatter::new(true); + println!("{}", dlf.format(&dl)); +} diff --git a/vendor/annotate-snippets/src/display_list/from_snippet.rs b/vendor/annotate-snippets/src/display_list/from_snippet.rs new file mode 100644 index 0000000000..e3d79ed4b1 --- /dev/null +++ b/vendor/annotate-snippets/src/display_list/from_snippet.rs @@ -0,0 +1,403 @@ +//! Trait for converting `Snippet` to `DisplayList`. +use super::*; +use crate::snippet; + +fn format_label(label: Option<&str>, style: Option) -> Vec { + let mut result = vec![]; + if let Some(label) = label { + let elements: Vec<&str> = label.split("__").collect(); + for (idx, element) in elements.iter().enumerate() { + let element_style = match style { + Some(s) => s, + None => { + if idx % 2 == 0 { + DisplayTextStyle::Regular + } else { + DisplayTextStyle::Emphasis + } + } + }; + result.push(DisplayTextFragment { + content: element.to_string(), + style: element_style, + }); + } + } + result +} + +fn format_title(annotation: &snippet::Annotation) -> DisplayLine { + let label = annotation.label.clone().unwrap_or_default(); + DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::from(annotation.annotation_type), + id: annotation.id.clone(), + label: format_label(Some(&label), Some(DisplayTextStyle::Emphasis)), + }, + source_aligned: false, + continuation: false, + }) +} + +fn format_annotation(annotation: &snippet::Annotation) -> Vec { + let mut result = vec![]; + let label = annotation.label.clone().unwrap_or_default(); + for (i, line) in label.lines().enumerate() { + result.push(DisplayLine::Raw(DisplayRawLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::from(annotation.annotation_type), + id: None, + label: format_label(Some(line), None), + }, + source_aligned: true, + continuation: i != 0, + })); + } + result +} + +fn format_slice(slice: &snippet::Slice, is_first: bool, has_footer: bool) -> Vec { + let mut body = format_body(slice, has_footer); + let mut result = vec![]; + + let header = format_header(slice, &body, is_first); + if let Some(header) = header { + result.push(header); + } + result.append(&mut body); + result +} + +fn format_header( + slice: &snippet::Slice, + body: &[DisplayLine], + is_first: bool, +) -> Option { + let main_annotation = slice.annotations.get(0); + + let display_header = if is_first { + DisplayHeaderType::Initial + } else { + DisplayHeaderType::Continuation + }; + + if let Some(annotation) = main_annotation { + let mut col = 1; + let mut row = slice.line_start; + + for item in body.iter() { + if let DisplayLine::Source { + line: DisplaySourceLine::Content { range, .. }, + .. + } = item + { + if annotation.range.0 >= range.0 && annotation.range.0 <= range.1 { + col = annotation.range.0 - range.0; + break; + } + row += 1; + } + } + if let Some(ref path) = slice.origin { + return Some(DisplayLine::Raw(DisplayRawLine::Origin { + path: path.to_string(), + pos: Some((row, col)), + header_type: display_header, + })); + } + } + if let Some(ref path) = slice.origin { + return Some(DisplayLine::Raw(DisplayRawLine::Origin { + path: path.to_string(), + pos: None, + header_type: display_header, + })); + } + None +} + +fn fold_body(body: &[DisplayLine]) -> Vec { + let mut new_body = vec![]; + + let mut no_annotation_lines_counter = 0; + let mut idx = 0; + + while idx < body.len() { + match body[idx] { + DisplayLine::Source { + line: DisplaySourceLine::Annotation { .. }, + ref inline_marks, + .. + } => { + if no_annotation_lines_counter > 2 { + let fold_start = idx - no_annotation_lines_counter; + let fold_end = idx; + let pre_len = if no_annotation_lines_counter > 8 { + 4 + } else { + 0 + }; + let post_len = if no_annotation_lines_counter > 8 { + 2 + } else { + 1 + }; + for item in body.iter().take(fold_start + pre_len).skip(fold_start) { + new_body.push(item.clone()); + } + new_body.push(DisplayLine::Fold { + inline_marks: inline_marks.clone(), + }); + for item in body.iter().take(fold_end).skip(fold_end - post_len) { + new_body.push(item.clone()); + } + } else { + let start = idx - no_annotation_lines_counter; + for item in body.iter().take(idx).skip(start) { + new_body.push(item.clone()); + } + } + no_annotation_lines_counter = 0; + } + DisplayLine::Source { .. } => { + no_annotation_lines_counter += 1; + idx += 1; + continue; + } + _ => { + no_annotation_lines_counter += 1; + } + } + new_body.push(body[idx].clone()); + idx += 1; + } + + new_body +} + +fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec { + let mut body = vec![]; + + let mut current_line = slice.line_start; + let mut current_index = 0; + let mut line_index_ranges = vec![]; + + for line in slice.source.lines() { + let line_length = line.chars().count() + 1; + let line_range = (current_index, current_index + line_length); + body.push(DisplayLine::Source { + lineno: Some(current_line), + inline_marks: vec![], + line: DisplaySourceLine::Content { + text: line.to_string(), + range: line_range, + }, + }); + line_index_ranges.push(line_range); + current_line += 1; + current_index += line_length + 1; + } + + let mut annotation_line_count = 0; + let mut annotations = slice.annotations.clone(); + for idx in 0..body.len() { + let (line_start, line_end) = line_index_ranges[idx]; + // It would be nice to use filter_drain here once it's stable. + annotations = annotations + .into_iter() + .filter(|annotation| { + let body_idx = idx + annotation_line_count; + let annotation_type = match annotation.annotation_type { + snippet::AnnotationType::Error => DisplayAnnotationType::None, + snippet::AnnotationType::Warning => DisplayAnnotationType::None, + _ => DisplayAnnotationType::from(annotation.annotation_type), + }; + match annotation.range { + (start, _) if start > line_end => true, + (start, end) if start >= line_start && end <= line_end + 1 => { + let range = (start - line_start, end - line_start); + body.insert( + body_idx + 1, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + annotation: Annotation { + annotation_type, + id: None, + label: format_label(Some(&annotation.label), None), + }, + range, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + annotation_part: DisplayAnnotationPart::Standalone, + }, + }, + ); + annotation_line_count += 1; + false + } + (start, end) if start >= line_start && start <= line_end && end > line_end => { + if start - line_start == 0 { + if let DisplayLine::Source { + ref mut inline_marks, + .. + } = body[body_idx] + { + inline_marks.push(DisplayMark { + mark_type: DisplayMarkType::AnnotationStart, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }); + } + } else { + let range = (start - line_start, start - line_start + 1); + body.insert( + body_idx + 1, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Annotation { + annotation: Annotation { + annotation_type: DisplayAnnotationType::None, + id: None, + label: vec![], + }, + range, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + annotation_part: DisplayAnnotationPart::MultilineStart, + }, + }, + ); + annotation_line_count += 1; + } + true + } + (start, end) if start < line_start && end > line_end => { + if let DisplayLine::Source { + ref mut inline_marks, + .. + } = body[body_idx] + { + inline_marks.push(DisplayMark { + mark_type: DisplayMarkType::AnnotationThrough, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }); + } + true + } + (start, end) if start < line_start && end >= line_start && end <= line_end => { + if let DisplayLine::Source { + ref mut inline_marks, + .. + } = body[body_idx] + { + inline_marks.push(DisplayMark { + mark_type: DisplayMarkType::AnnotationThrough, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }); + } + let range = (end - line_start, end - line_start + 1); + body.insert( + body_idx + 1, + DisplayLine::Source { + lineno: None, + inline_marks: vec![DisplayMark { + mark_type: DisplayMarkType::AnnotationThrough, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + }], + line: DisplaySourceLine::Annotation { + annotation: Annotation { + annotation_type, + id: None, + label: format_label(Some(&annotation.label), None), + }, + range, + annotation_type: DisplayAnnotationType::from( + annotation.annotation_type, + ), + annotation_part: DisplayAnnotationPart::MultilineEnd, + }, + }, + ); + annotation_line_count += 1; + false + } + _ => true, + } + }) + .collect(); + } + + if slice.fold { + body = fold_body(&body); + } + + body.insert( + 0, + DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }, + ); + if has_footer { + body.push(DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }); + } else if let Some(DisplayLine::Source { .. }) = body.last() { + body.push(DisplayLine::Source { + lineno: None, + inline_marks: vec![], + line: DisplaySourceLine::Empty, + }); + } + body +} + +impl From for DisplayList { + fn from(snippet: snippet::Snippet) -> Self { + let mut body = vec![]; + if let Some(annotation) = snippet.title { + body.push(format_title(&annotation)); + } + + for (idx, slice) in snippet.slices.iter().enumerate() { + body.append(&mut format_slice( + &slice, + idx == 0, + !snippet.footer.is_empty(), + )); + } + + for annotation in snippet.footer { + body.append(&mut format_annotation(&annotation)); + } + + Self { body } + } +} + +impl From for DisplayAnnotationType { + fn from(at: snippet::AnnotationType) -> Self { + match at { + snippet::AnnotationType::Error => DisplayAnnotationType::Error, + snippet::AnnotationType::Warning => DisplayAnnotationType::Warning, + snippet::AnnotationType::Info => DisplayAnnotationType::Info, + snippet::AnnotationType::Note => DisplayAnnotationType::Note, + snippet::AnnotationType::Help => DisplayAnnotationType::Help, + } + } +} diff --git a/vendor/annotate-snippets/src/display_list/mod.rs b/vendor/annotate-snippets/src/display_list/mod.rs new file mode 100644 index 0000000000..5e0b393d66 --- /dev/null +++ b/vendor/annotate-snippets/src/display_list/mod.rs @@ -0,0 +1,124 @@ +//! display_list module stores the output model for the snippet. +//! +//! `DisplayList` is a central structure in the crate, which contains +//! the structured list of lines to be displayed. +//! +//! It is made of two types of lines: `Source` and `Raw`. All `Source` lines +//! are structured using four columns: +//! +//! ```text +//! /------------ (1) Line number column. +//! | /--------- (2) Line number column delimiter. +//! | | /------- (3) Inline marks column. +//! | | | /--- (4) Content column with the source and annotations for slices. +//! | | | | +//! ============================================================================= +//! error[E0308]: mismatched types +//! --> src/format.rs:51:5 +//! | +//! 151 | / fn test() -> String { +//! 152 | | return "test"; +//! 153 | | } +//! | |___^ error: expected `String`, for `&str`. +//! | +//! ``` +//! +//! The first two lines of the example above are `Raw` lines, while the rest +//! are `Source` lines. +//! +//! `DisplayList` does not store column alignment information, and those are +//! only calculated by the `DisplayListFormatter` using information such as +//! styling. +//! +//! The above snippet has been built out of the following structure: +//! +//! ``` +//! use annotate_snippets::display_list::*; +//! +//! let dl = DisplayList { +//! body: vec![ +//! DisplayLine::Raw(DisplayRawLine::Annotation { +//! annotation: Annotation { +//! annotation_type: DisplayAnnotationType::Error, +//! id: Some("E0308".to_string()), +//! label: vec![ +//! DisplayTextFragment { +//! content: "mismatched types".to_string(), +//! style: DisplayTextStyle::Regular, +//! } +//! ] +//! }, +//! source_aligned: false, +//! continuation: false, +//! }), +//! DisplayLine::Raw(DisplayRawLine::Origin { +//! path: "src/format.rs".to_string(), +//! pos: Some((51, 5)), +//! header_type: DisplayHeaderType::Initial, +//! }), +//! DisplayLine::Source { +//! lineno: Some(151), +//! inline_marks: vec![ +//! DisplayMark { +//! mark_type: DisplayMarkType::AnnotationStart, +//! annotation_type: DisplayAnnotationType::Error, +//! } +//! ], +//! line: DisplaySourceLine::Content { +//! text: " fn test() -> String {".to_string(), +//! range: (0, 24) +//! } +//! }, +//! DisplayLine::Source { +//! lineno: Some(152), +//! inline_marks: vec![ +//! DisplayMark { +//! mark_type: DisplayMarkType::AnnotationThrough, +//! annotation_type: DisplayAnnotationType::Error, +//! } +//! ], +//! line: DisplaySourceLine::Content { +//! text: " return \"test\";".to_string(), +//! range: (25, 46) +//! } +//! }, +//! DisplayLine::Source { +//! lineno: Some(153), +//! inline_marks: vec![ +//! DisplayMark { +//! mark_type: DisplayMarkType::AnnotationThrough, +//! annotation_type: DisplayAnnotationType::Error, +//! } +//! ], +//! line: DisplaySourceLine::Content { +//! text: " }".to_string(), +//! range: (47, 51) +//! } +//! }, +//! DisplayLine::Source { +//! lineno: None, +//! inline_marks: vec![], +//! line: DisplaySourceLine::Annotation { +//! annotation: Annotation { +//! annotation_type: DisplayAnnotationType::Error, +//! id: None, +//! label: vec![ +//! DisplayTextFragment { +//! content: "expected `String`, for `&str`.".to_string(), +//! style: DisplayTextStyle::Regular, +//! } +//! ] +//! }, +//! range: (3, 4), +//! annotation_type: DisplayAnnotationType::Error, +//! annotation_part: DisplayAnnotationPart::MultilineEnd, +//! } +//! +//! } +//! ] +//! }; +//! ``` +mod from_snippet; +mod structs; + +pub use self::structs::*; diff --git a/vendor/annotate-snippets/src/display_list/structs.rs b/vendor/annotate-snippets/src/display_list/structs.rs new file mode 100644 index 0000000000..ecd9eb49d8 --- /dev/null +++ b/vendor/annotate-snippets/src/display_list/structs.rs @@ -0,0 +1,253 @@ +/// List of lines to be displayed. +#[derive(Debug, Clone, PartialEq)] +pub struct DisplayList { + pub body: Vec, +} + +impl From> for DisplayList { + fn from(body: Vec) -> Self { + Self { body } + } +} + +/// Inline annotation which can be used in either Raw or Source line. +#[derive(Debug, Clone, PartialEq)] +pub struct Annotation { + pub annotation_type: DisplayAnnotationType, + pub id: Option, + pub label: Vec, +} + +/// A single line used in `DisplayList`. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayLine { + /// A line with `lineno` portion of the slice. + Source { + lineno: Option, + inline_marks: Vec, + line: DisplaySourceLine, + }, + + /// A line indicating a folded part of the slice. + Fold { inline_marks: Vec }, + + /// A line which is displayed outside of slices. + Raw(DisplayRawLine), +} + +/// A source line. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplaySourceLine { + /// A line with the content of the Slice. + Content { + text: String, + range: (usize, usize), // meta information for annotation placement. + }, + + /// An annotation line which is displayed in context of the slice. + Annotation { + annotation: Annotation, + range: (usize, usize), + annotation_type: DisplayAnnotationType, + annotation_part: DisplayAnnotationPart, + }, + + /// An empty source line. + Empty, +} + +/// Raw line - a line which does not have the `lineno` part and is not considered +/// a part of the snippet. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayRawLine { + /// A line which provides information about the location of the given + /// slice in the project structure. + Origin { + path: String, + pos: Option<(usize, usize)>, + header_type: DisplayHeaderType, + }, + + /// An annotation line which is not part of any snippet. + Annotation { + annotation: Annotation, + + /// If set to `true`, the annotation will be aligned to the + /// lineno delimiter of the snippet. + source_aligned: bool, + /// If set to `true`, only the label of the `Annotation` will be + /// displayed. It allows for a multiline annotation to be aligned + /// without displaing the meta information (`type` and `id`) to be + /// displayed on each line. + continuation: bool, + }, +} + +/// An inline text fragment which any label is composed of. +#[derive(Debug, Clone, PartialEq)] +pub struct DisplayTextFragment { + pub content: String, + pub style: DisplayTextStyle, +} + +/// A style for the `DisplayTextFragment` which can be visually formatted. +/// +/// This information may be used to emphasis parts of the label. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum DisplayTextStyle { + Regular, + Emphasis, +} + +/// An indicator of what part of the annotation a given `Annotation` is. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayAnnotationPart { + /// A standalone, single-line annotation. + Standalone, + /// A continuation of a multi-line label of an annotation. + LabelContinuation, + /// A consequitive annotation in case multiple annotations annotate a single line. + Consequitive, + /// A line starting a multiline annotation. + MultilineStart, + /// A line ending a multiline annotation. + MultilineEnd, +} + +/// A visual mark used in `inline_marks` field of the `DisplaySourceLine`. +#[derive(Debug, Clone, PartialEq)] +pub struct DisplayMark { + pub mark_type: DisplayMarkType, + pub annotation_type: DisplayAnnotationType, +} + +/// A type of the `DisplayMark`. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayMarkType { + /// A mark indicating a multiline annotation going through the current line. + /// + /// Example: + /// ``` + /// use annotate_snippets::display_list::*; + /// use annotate_snippets::formatter::DisplayListFormatter; + /// + /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// + /// let dl = DisplayList { + /// body: vec![ + /// DisplayLine::Source { + /// lineno: Some(51), + /// inline_marks: vec![ + /// DisplayMark { + /// mark_type: DisplayMarkType::AnnotationThrough, + /// annotation_type: DisplayAnnotationType::Error, + /// } + /// ], + /// line: DisplaySourceLine::Content { + /// text: "Example".to_string(), + /// range: (0, 7), + /// } + /// } + /// ] + /// }; + /// assert_eq!(dlf.format(&dl), "51 | | Example"); + /// ``` + AnnotationThrough, + + /// A mark indicating a multiline annotation starting on the given line. + /// + /// Example: + /// ``` + /// use annotate_snippets::display_list::*; + /// use annotate_snippets::formatter::DisplayListFormatter; + /// + /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// + /// let dl = DisplayList { + /// body: vec![ + /// DisplayLine::Source { + /// lineno: Some(51), + /// inline_marks: vec![ + /// DisplayMark { + /// mark_type: DisplayMarkType::AnnotationStart, + /// annotation_type: DisplayAnnotationType::Error, + /// } + /// ], + /// line: DisplaySourceLine::Content { + /// text: "Example".to_string(), + /// range: (0, 7), + /// } + /// } + /// ] + /// }; + /// assert_eq!(dlf.format(&dl), "51 | / Example"); + /// ``` + AnnotationStart, +} + +/// A type of the `Annotation` which may impact the sigils, style or text displayed. +/// +/// There are several ways in which the `DisplayListFormatter` uses this information +/// when formatting the `DisplayList`: +/// +/// * An annotation may display the name of the type like `error` or `info`. +/// * An underline for `Error` may be `^^^` while for `Warning` it coule be `---`. +/// * `ColorStylesheet` may use different colors for different annotations. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayAnnotationType { + None, + Error, + Warning, + Info, + Note, + Help, +} + +/// Information whether the header is the initial one or a consequitive one +/// for multi-slice cases. +#[derive(Debug, Clone, PartialEq)] +pub enum DisplayHeaderType { + /// Initial header is the first header in the snippet. + /// + /// Example: + /// ``` + /// use annotate_snippets::display_list::*; + /// use annotate_snippets::formatter::DisplayListFormatter; + /// + /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// + /// let dl = DisplayList { + /// body: vec![ + /// DisplayLine::Raw(DisplayRawLine::Origin { + /// path: "file1.rs".to_string(), + /// pos: Some((51, 5)), + /// header_type: DisplayHeaderType::Initial, + /// }) + /// ] + /// }; + /// assert_eq!(dlf.format(&dl), "--> file1.rs:51:5"); + /// ``` + Initial, + + /// Continuation marks all headers of following slices in the snippet. + /// + /// Example: + /// ``` + /// use annotate_snippets::display_list::*; + /// use annotate_snippets::formatter::DisplayListFormatter; + /// + /// let dlf = DisplayListFormatter::new(false); // Don't use colors + /// + /// let dl = DisplayList { + /// body: vec![ + /// DisplayLine::Raw(DisplayRawLine::Origin { + /// path: "file1.rs".to_string(), + /// pos: Some((51, 5)), + /// header_type: DisplayHeaderType::Continuation, + /// }) + /// ] + /// }; + /// assert_eq!(dlf.format(&dl), "::: file1.rs:51:5"); + /// ``` + Continuation, +} diff --git a/vendor/annotate-snippets/src/formatter/mod.rs b/vendor/annotate-snippets/src/formatter/mod.rs new file mode 100644 index 0000000000..45fee74ce0 --- /dev/null +++ b/vendor/annotate-snippets/src/formatter/mod.rs @@ -0,0 +1,345 @@ +//! DisplayListFormatter is a module handling the formatting of a +//! `DisplayList` into a formatted string. +//! +//! Besides formatting into a string it also uses a `style::Stylesheet` to +//! provide additional styling like colors and emphasis to the text. + +pub mod style; + +use self::style::{Style, StyleClass, Stylesheet}; +use crate::display_list::*; +use std::cmp; + +use crate::stylesheets::no_color::NoColorStylesheet; +#[cfg(feature = "ansi_term")] +use crate::stylesheets::color::AnsiTermStylesheet; + +fn repeat_char(c: char, n: usize) -> String { + let mut s = String::with_capacity(c.len_utf8()); + s.push(c); + s.repeat(n) +} + +/// DisplayListFormatter' constructor accepts a single argument which +/// allows the formatter to optionally apply colors and emphasis +/// using `ansi_term` crate. +/// +/// Example: +/// +/// ``` +/// use annotate_snippets::formatter::DisplayListFormatter; +/// use annotate_snippets::display_list::{DisplayList, DisplayLine, DisplaySourceLine}; +/// +/// let dlf = DisplayListFormatter::new(false); // Don't use colors +/// +/// let dl = DisplayList { +/// body: vec![ +/// DisplayLine::Source { +/// lineno: Some(192), +/// inline_marks: vec![], +/// line: DisplaySourceLine::Content { +/// text: "Example line of text".into(), +/// range: (0, 21) +/// } +/// } +/// ] +/// }; +/// assert_eq!(dlf.format(&dl), "192 | Example line of text"); +/// ``` +pub struct DisplayListFormatter { + stylesheet: Box, +} + +impl DisplayListFormatter { + /// Constructor for the struct. The argument `color` selects + /// the stylesheet depending on the user preferences and `ansi_term` + /// crate availability. + pub fn new(color: bool) -> Self { + if color { + Self { + #[cfg(feature = "ansi_term")] + stylesheet: Box::new(AnsiTermStylesheet {}), + #[cfg(not(feature = "ansi_term"))] + stylesheet: Box::new(NoColorStylesheet {}), + } + } else { + Self { + stylesheet: Box::new(NoColorStylesheet {}), + } + } + } + + /// Formats a `DisplayList` into a String. + pub fn format(&self, dl: &DisplayList) -> String { + let lineno_width = dl.body.iter().fold(0, |max, line| match line { + DisplayLine::Source { + lineno: Some(lineno), + .. + } => cmp::max(lineno.to_string().len(), max), + _ => max, + }); + let inline_marks_width = dl.body.iter().fold(0, |max, line| match line { + DisplayLine::Source { inline_marks, .. } => cmp::max(inline_marks.len(), max), + _ => max, + }); + + dl.body + .iter() + .map(|line| self.format_line(line, lineno_width, inline_marks_width)) + .collect::>() + .join("\n") + } + + fn format_annotation_type(&self, annotation_type: &DisplayAnnotationType) -> &'static str { + match annotation_type { + DisplayAnnotationType::Error => "error", + DisplayAnnotationType::Warning => "warning", + DisplayAnnotationType::Info => "info", + DisplayAnnotationType::Note => "note", + DisplayAnnotationType::Help => "help", + DisplayAnnotationType::None => "", + } + } + + fn get_annotation_style(&self, annotation_type: &DisplayAnnotationType) -> Box"#); +test!( + script_literal, + r#""# +); +test!( + style_literal, + r#""# +); test!(xmp_literal, r#"(x & 1) < 2; y > "foo" + 'bar'"#); -test!(iframe_literal, r#""#); -test!(noembed_literal, r#"(x & 1) < 2; y > "foo" + 'bar'"#); -test!(noframes_literal, r#"(x & 1) < 2; y > "foo" + 'bar'"#); +test!( + iframe_literal, + r#""# +); +test!( + noembed_literal, + r#"(x & 1) < 2; y > "foo" + 'bar'"# +); +test!( + noframes_literal, + r#"(x & 1) < 2; y > "foo" + 'bar'"# +); test!(pre_lf_0, "
foo bar
"); test!(pre_lf_1, "
\nfoo bar
", "
foo bar
"); test!(pre_lf_2, "
\n\nfoo bar
", "
\nfoo bar
"); test!(textarea_lf_0, ""); -test!(textarea_lf_1, "", ""); -test!(textarea_lf_2, "", ""); +test!( + textarea_lf_1, + "", + "" +); +test!( + textarea_lf_2, + "", + "" +); test!(listing_lf_0, "foo bar"); -test!(listing_lf_1, "\nfoo bar", "foo bar"); -test!(listing_lf_2, "\n\nfoo bar", "\nfoo bar"); +test!( + listing_lf_1, + "\nfoo bar", + "foo bar" +); +test!( + listing_lf_2, + "\n\nfoo bar", + "\nfoo bar" +); test!(comment_1, r#"

hi

"#); test!(comment_2, r#"

hi

"#); @@ -193,10 +239,26 @@ test_no_parse!(malformed_tokens, r#"foo
"#); #[test] fn doctype() { - let dom = parse_document( - RcDom::default(), ParseOpts::default()).one(""); - dom.document.children.borrow_mut().truncate(1); // Remove + let dom = parse_document(RcDom::default(), ParseOpts::default()).one(""); + dom.document.children.borrow_mut().truncate(1); // Remove let mut result = vec![]; serialize(&mut result, &dom.document, Default::default()).unwrap(); assert_eq!(String::from_utf8(result).unwrap(), ""); } + +#[test] +fn deep_tree() { + let parser = parse_fragment( + RcDom::default(), + ParseOpts::default(), + QualName::new(None, ns!(html), local_name!("div")), + vec![], + ); + let src = String::from("".repeat(60_000)); + let dom = parser.one(src); + let document = &dom.document; + let opts = SerializeOpts::default(); + let mut ret_val = Vec::new(); + serialize(&mut ret_val, document, opts) + .expect("Writing to a string shouldn't fail (expect on OOM)"); +} diff --git a/vendor/html5ever/tests/tokenizer.rs b/vendor/html5ever/tests/tokenizer.rs index 7093a181bb..ca4ecb7947 100644 --- a/vendor/html5ever/tests/tokenizer.rs +++ b/vendor/html5ever/tests/tokenizer.rs @@ -9,53 +9,53 @@ extern crate rustc_serialize; extern crate rustc_test as test; -#[macro_use] extern crate html5ever; +#[macro_use] +extern crate html5ever; mod foreach_html5lib_test; use foreach_html5lib_test::foreach_html5lib_test; -use std::{char, env}; +use rustc_serialize::json::Json; +use std::borrow::Cow::Borrowed; +use std::collections::BTreeMap; +use std::default::Default; use std::ffi::OsStr; use std::mem::replace; -use std::default::Default; use std::path::Path; -use test::{TestDesc, TestDescAndFn, DynTestName, DynTestFn}; -use rustc_serialize::json::Json; -use std::collections::BTreeMap; -use std::borrow::Cow::Borrowed; +use std::{char, env}; +use test::{DynTestFn, DynTestName, TestDesc, TestDescAndFn}; -use html5ever::{LocalName, QualName}; -use html5ever::tokenizer::{Doctype, StartTag, EndTag, Tag}; -use html5ever::tokenizer::{Token, DoctypeToken, TagToken, CommentToken}; -use html5ever::tokenizer::{CharacterTokens, NullCharacterToken, EOFToken, ParseError}; -use html5ever::tokenizer::{TokenSink, Tokenizer, TokenizerOpts, TokenSinkResult}; -use html5ever::tokenizer::{BufferQueue}; -use html5ever::tokenizer::states::{Plaintext, RawData, Rcdata, Rawtext}; use html5ever::tendril::*; -use html5ever::{Attribute}; - +use html5ever::tokenizer::states::{Plaintext, RawData, Rawtext, Rcdata}; +use html5ever::tokenizer::BufferQueue; +use html5ever::tokenizer::{CharacterTokens, EOFToken, NullCharacterToken, ParseError}; +use html5ever::tokenizer::{CommentToken, DoctypeToken, TagToken, Token}; +use html5ever::tokenizer::{Doctype, EndTag, StartTag, Tag}; +use html5ever::tokenizer::{TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts}; +use html5ever::Attribute; +use html5ever::{LocalName, QualName}; // Return all ways of splitting the string into at most n // possibly-empty pieces. fn splits(s: &str, n: usize) -> Vec> { if n == 1 { - return vec!(vec!(s.to_tendril())); + return vec![vec![s.to_tendril()]]; } - let mut points: Vec = s.char_indices().map(|(n,_)| n).collect(); + let mut points: Vec = s.char_indices().map(|(n, _)| n).collect(); points.push(s.len()); // do this with iterators? - let mut out = vec!(); + let mut out = vec![]; for p in points.into_iter() { let y = &s[p..]; - for mut x in splits(&s[..p], n-1).into_iter() { + for mut x in splits(&s[..p], n - 1).into_iter() { x.push(y.to_tendril()); out.push(x); } } - out.extend(splits(s, n-1).into_iter()); + out.extend(splits(s, n - 1).into_iter()); out } @@ -68,7 +68,7 @@ struct TokenLogger { impl TokenLogger { fn new(exact_errors: bool) -> TokenLogger { TokenLogger { - tokens: vec!(), + tokens: vec![], current_str: StrTendril::new(), exact_errors: exact_errors, } @@ -100,14 +100,16 @@ impl TokenSink for TokenLogger { match token { CharacterTokens(b) => { self.current_str.push_slice(&b); - } + }, NullCharacterToken => { self.current_str.push_char('\0'); - } + }, - ParseError(_) => if self.exact_errors { - self.push(ParseError(Borrowed(""))); + ParseError(_) => { + if self.exact_errors { + self.push(ParseError(Borrowed(""))); + } }, TagToken(mut t) => { @@ -117,12 +119,12 @@ impl TokenSink for TokenLogger { match t.kind { EndTag => { t.self_closing = false; - t.attrs = vec!(); - } + t.attrs = vec![]; + }, _ => t.attrs.sort_by(|a1, a2| a1.name.cmp(&a2.name)), } self.push(TagToken(t)); - } + }, EOFToken => (), @@ -220,23 +222,25 @@ fn json_to_token(js: &Json) -> Token { "StartTag" => TagToken(Tag { kind: StartTag, name: LocalName::from(&*args[0].get_str()), - attrs: args[1].get_obj().iter().map(|(k,v)| { - Attribute { + attrs: args[1] + .get_obj() + .iter() + .map(|(k, v)| Attribute { name: QualName::new(None, ns!(), LocalName::from(&**k)), - value: v.get_tendril() - } - }).collect(), + value: v.get_tendril(), + }) + .collect(), self_closing: match args.get(2) { Some(b) => b.get_bool(), None => false, - } + }, }), "EndTag" => TagToken(Tag { kind: EndTag, name: LocalName::from(&*args[0].get_str()), - attrs: vec!(), - self_closing: false + attrs: vec![], + self_closing: false, }), "Comment" => CommentToken(args[0].get_tendril()), @@ -245,7 +249,6 @@ fn json_to_token(js: &Json) -> Token { // We don't need to produce NullCharacterToken because // the TokenLogger will convert them to CharacterTokens. - _ => panic!("don't understand token {:?}", parts), } } @@ -256,11 +259,15 @@ fn json_to_tokens(js: &Json, exact_errors: bool) -> Vec { // by an ignored error. let mut sink = TokenLogger::new(exact_errors); for tok in js.get_list().iter() { - assert_eq!(match *tok { - Json::String(ref s) - if &s[..] == "ParseError" => sink.process_token(ParseError(Borrowed("")), 0), - _ => sink.process_token(json_to_token(tok), 0), - }, TokenSinkResult::Continue); + assert_eq!( + match *tok { + Json::String(ref s) if &s[..] == "ParseError" => { + sink.process_token(ParseError(Borrowed("")), 0) + }, + _ => sink.process_token(json_to_token(tok), 0), + }, + TokenSinkResult::Continue + ); } sink.get_tokens() } @@ -278,8 +285,7 @@ fn unescape(s: &str) -> Option { } drop(it.next()); let hex: String = it.by_ref().take(4).collect(); - match u32::from_str_radix(&hex, 16).ok() - .and_then(char::from_u32) { + match u32::from_str_radix(&hex, 16).ok().and_then(char::from_u32) { // Some of the tests use lone surrogates, but we have no // way to represent them in the UTF-8 input to our parser. // Since these can only come from script, we will catch @@ -287,7 +293,7 @@ fn unescape(s: &str) -> Option { None => return None, Some(c) => out.push(c), } - } + }, Some(c) => out.push(c), } } @@ -301,17 +307,16 @@ fn unescape_json(js: &Json) -> Json { Json::Array(ref xs) => Json::Array(xs.iter().map(unescape_json).collect()), Json::Object(ref obj) => { let mut new_obj = BTreeMap::new(); - for (k,v) in obj.iter() { + for (k, v) in obj.iter() { new_obj.insert(k.clone(), unescape_json(v)); } Json::Object(new_obj) - } + }, _ => js.clone(), } } -fn mk_test(desc: String, input: String, expect: Json, opts: TokenizerOpts) - -> TestDescAndFn { +fn mk_test(desc: String, input: String, expect: Json, opts: TokenizerOpts) -> TestDescAndFn { TestDescAndFn { desc: TestDesc::new(DynTestName(desc)), testfn: DynTestFn(Box::new(move || { @@ -325,8 +330,10 @@ fn mk_test(desc: String, input: String, expect: Json, opts: TokenizerOpts) let output = tokenize(input.clone(), opts.clone()); let expect_toks = json_to_tokens(&expect, opts.exact_errors); if output != expect_toks { - panic!("\ninput: {:?}\ngot: {:?}\nexpected: {:?}", - input, output, expect); + panic!( + "\ninput: {:?}\ngot: {:?}\nexpected: {:?}", + input, output, expect + ); } } })), @@ -337,12 +344,18 @@ fn mk_tests(tests: &mut Vec, filename: &str, js: &Json) { let obj = js.get_obj(); let mut input = js.find("input").unwrap().get_str(); let mut expect = js.find("output").unwrap().clone(); - let desc = format!("tok: {}: {}", - filename, js.find("description").unwrap().get_str()); + let desc = format!( + "tok: {}: {}", + filename, + js.find("description").unwrap().get_str() + ); // "Double-escaped" tests require additional processing of // the input and output. - if obj.get(&"doubleEscaped".to_string()).map_or(false, |j| j.get_bool()) { + if obj + .get(&"doubleEscaped".to_string()) + .map_or(false, |j| j.get_bool()) + { match unescape(&input) { None => return, Some(i) => input = i, @@ -355,14 +368,18 @@ fn mk_tests(tests: &mut Vec, filename: &str, js: &Json) { // Some tests want to start in a state other than Data. let state_overrides = match obj.get(&"initialStates".to_string()) { - Some(&Json::Array(ref xs)) => xs.iter().map(|s| - Some(match &s.get_str()[..] { - "PLAINTEXT state" => Plaintext, - "RAWTEXT state" => RawData(Rawtext), - "RCDATA state" => RawData(Rcdata), - s => panic!("don't know state {}", s), - })).collect(), - None => vec!(None), + Some(&Json::Array(ref xs)) => xs + .iter() + .map(|s| { + Some(match &s.get_str()[..] { + "PLAINTEXT state" => Plaintext, + "RAWTEXT state" => RawData(Rawtext), + "RCDATA state" => RawData(Rcdata), + s => panic!("don't know state {}", s), + }) + }) + .collect(), + None => vec![None], _ => panic!("don't understand initialStates value"), }; @@ -372,45 +389,58 @@ fn mk_tests(tests: &mut Vec, filename: &str, js: &Json) { let mut newdesc = desc.clone(); match state { Some(s) => newdesc = format!("{} (in state {:?})", newdesc, s), - None => (), + None => (), }; if exact_errors { newdesc = format!("{} (exact errors)", newdesc); } - tests.push(mk_test(newdesc, input.clone(), expect.clone(), TokenizerOpts { - exact_errors: exact_errors, - initial_state: state, - last_start_tag_name: start_tag.clone(), - - // Not discarding a BOM is what the test suite expects; see - // https://github.com/html5lib/html5lib-tests/issues/2 - discard_bom: false, - - .. Default::default() - })); + tests.push(mk_test( + newdesc, + input.clone(), + expect.clone(), + TokenizerOpts { + exact_errors: exact_errors, + initial_state: state, + last_start_tag_name: start_tag.clone(), + + // Not discarding a BOM is what the test suite expects; see + // https://github.com/html5lib/html5lib-tests/issues/2 + discard_bom: false, + + ..Default::default() + }, + )); } } } fn tests(src_dir: &Path) -> Vec { - let mut tests = vec!(); - - foreach_html5lib_test(src_dir, "tokenizer", - OsStr::new("test"), |path, mut file| { - let js = Json::from_reader(&mut file).ok().expect("json parse error"); + let mut tests = vec![]; + + foreach_html5lib_test( + src_dir, + "tokenizer", + OsStr::new("test"), + |path, mut file| { + let js = Json::from_reader(&mut file).ok().expect("json parse error"); + + match js.get_obj().get(&"tests".to_string()) { + Some(&Json::Array(ref lst)) => { + for test in lst.iter() { + mk_tests( + &mut tests, + path.file_name().unwrap().to_str().unwrap(), + test, + ); + } + }, - match js.get_obj().get(&"tests".to_string()) { - Some(&Json::Array(ref lst)) => { - for test in lst.iter() { - mk_tests(&mut tests, path.file_name().unwrap().to_str().unwrap(), test); - } + // xmlViolation.test doesn't follow this format. + _ => (), } - - // xmlViolation.test doesn't follow this format. - _ => (), - } - }); + }, + ); tests } diff --git a/vendor/html5ever/tests/tree_builder.rs b/vendor/html5ever/tests/tree_builder.rs index f169557e21..b91b7d4477 100644 --- a/vendor/html5ever/tests/tree_builder.rs +++ b/vendor/html5ever/tests/tree_builder.rs @@ -8,29 +8,29 @@ // except according to those terms. extern crate rustc_test as test; -#[macro_use] extern crate html5ever; +#[macro_use] +extern crate html5ever; mod foreach_html5lib_test; use foreach_html5lib_test::foreach_html5lib_test; -use std::{fs, io, env}; -use std::io::BufRead; +use std::collections::{HashMap, HashSet}; +use std::default::Default; use std::ffi::OsStr; +use std::io::BufRead; use std::iter::repeat; use std::mem::replace; -use std::default::Default; use std::path::Path; -use std::collections::{HashSet, HashMap}; -use test::{TestDesc, TestDescAndFn, DynTestName, TestFn}; +use std::{env, fs, io}; +use test::{DynTestName, TestDesc, TestDescAndFn, TestFn}; -use html5ever::{LocalName, QualName}; -use html5ever::{ParseOpts, parse_document, parse_fragment}; -use html5ever::rcdom::{NodeData, Handle, RcDom}; +use html5ever::rcdom::{Handle, NodeData, RcDom}; use html5ever::tendril::{StrTendril, TendrilSink}; +use html5ever::{parse_document, parse_fragment, ParseOpts}; +use html5ever::{LocalName, QualName}; - -fn parse_tests>(mut lines: It) -> Vec> { - let mut tests = vec!(); +fn parse_tests>(mut lines: It) -> Vec> { + let mut tests = vec![]; let mut test = HashMap::new(); let mut key: Option = None; let mut val = String::new(); @@ -64,7 +64,7 @@ fn parse_tests>(mut lines: It) -> Vec panic!("should not reach Document"), - NodeData::Doctype { ref name, ref public_id, ref system_id } => { + NodeData::Doctype { + ref name, + ref public_id, + ref system_id, + } => { buf.push_str("\n"); - } + }, NodeData::Text { ref contents } => { buf.push_str("\""); buf.push_str(&contents.borrow()); buf.push_str("\"\n"); - } + }, NodeData::Comment { ref contents } => { buf.push_str("\n"); - } + }, - NodeData::Element { ref name, ref attrs, .. } => { + NodeData::Element { + ref name, + ref attrs, + .. + } => { buf.push_str("<"); match name.ns { ns!(svg) => buf.push_str("svg "), @@ -118,42 +126,45 @@ fn serialize(buf: &mut String, indent: usize, handle: Handle) { for attr in attrs.into_iter() { buf.push_str("|"); - buf.push_str(&repeat(" ").take(indent+2).collect::()); + buf.push_str(&repeat(" ").take(indent + 2).collect::()); match attr.name.ns { ns!(xlink) => buf.push_str("xlink "), ns!(xml) => buf.push_str("xml "), ns!(xmlns) => buf.push_str("xmlns "), _ => (), } - buf.push_str(&format!("{}=\"{}\"\n", - attr.name.local, attr.value)); + buf.push_str(&format!("{}=\"{}\"\n", attr.name.local, attr.value)); } - } + }, - NodeData::ProcessingInstruction { .. } => unreachable!() + NodeData::ProcessingInstruction { .. } => unreachable!(), } for child in node.children.borrow().iter() { - serialize(buf, indent+2, child.clone()); + serialize(buf, indent + 2, child.clone()); } - if let NodeData::Element { template_contents: Some(ref content), .. } = node.data { + if let NodeData::Element { + template_contents: Some(ref content), + .. + } = node.data + { buf.push_str("|"); - buf.push_str(&repeat(" ").take(indent+2).collect::()); + buf.push_str(&repeat(" ").take(indent + 2).collect::()); buf.push_str("content\n"); for child in content.children.borrow().iter() { - serialize(buf, indent+4, child.clone()); + serialize(buf, indent + 4, child.clone()); } } } fn make_test( - tests: &mut Vec, - ignores: &HashSet, - filename: &str, - idx: usize, - fields: HashMap) { - + tests: &mut Vec, + ignores: &HashSet, + filename: &str, + idx: usize, + fields: HashMap, +) { let scripting_flags = &[false, true]; let scripting_flags = if fields.contains_key("script-off") { &scripting_flags[0..1] @@ -164,18 +175,17 @@ fn make_test( }; let name = format!("tb: {}-{}", filename, idx); for scripting_enabled in scripting_flags { - let test = make_test_desc_with_scripting_flag( - ignores, &name, &fields, *scripting_enabled); + let test = make_test_desc_with_scripting_flag(ignores, &name, &fields, *scripting_enabled); tests.push(test); } } fn make_test_desc_with_scripting_flag( - ignores: &HashSet, - name: &str, - fields: &HashMap, - scripting_enabled: bool) - -> TestDescAndFn { + ignores: &HashSet, + name: &str, + fields: &HashMap, + scripting_enabled: bool, +) -> TestDescAndFn { let get_field = |key| { let field = fields.get(key).expect("missing field"); field.trim_right_matches('\n').to_string() @@ -184,8 +194,9 @@ fn make_test_desc_with_scripting_flag( let mut data = fields.get("data").expect("missing data").to_string(); data.pop(); let expected = get_field("document"); - let context = fields.get("document-fragment") - .map(|field| context_name(field.trim_right_matches('\n'))); + let context = fields + .get("document-fragment") + .map(|field| context_name(field.trim_right_matches('\n'))); let ignore = ignores.contains(name); let mut name = name.to_owned(); if scripting_enabled { @@ -199,7 +210,7 @@ fn make_test_desc_with_scripting_flag( TestDescAndFn { desc: TestDesc { ignore: ignore, - .. TestDesc::new(DynTestName(name)) + ..TestDesc::new(DynTestName(name)) }, testfn: TestFn::dyn_test_fn(move || { // Do this here because Tendril isn't Send. @@ -217,7 +228,7 @@ fn make_test_desc_with_scripting_flag( .one(data.clone()); // fragment case: serialize children of the html element // rather than children of the document - let doc = dom.document; + let doc = &dom.document; let root = &doc.children.borrow()[0]; for child in root.children.borrow().iter() { serialize(&mut result, 1, child.clone()); @@ -225,11 +236,13 @@ fn make_test_desc_with_scripting_flag( }, }; let len = result.len(); - result.truncate(len - 1); // drop the trailing newline + result.truncate(len - 1); // drop the trailing newline if result != expected { - panic!("\ninput: {}\ngot:\n{}\nexpected:\n{}\n", - data, result, expected); + panic!( + "\ninput: {}\ngot:\n{}\nexpected:\n{}\n", + data, result, expected + ); } }), } @@ -246,20 +259,28 @@ fn context_name(context: &str) -> QualName { } fn tests(src_dir: &Path, ignores: &HashSet) -> Vec { - let mut tests = vec!(); - - foreach_html5lib_test(src_dir, "tree-construction", - OsStr::new("dat"), |path, file| { - let buf = io::BufReader::new(file); - let lines = buf.lines() - .map(|res| res.ok().expect("couldn't read")); - let data = parse_tests(lines); - - for (i, test) in data.into_iter().enumerate() { - make_test(&mut tests, ignores, path.file_name().unwrap().to_str().unwrap(), - i, test); - } - }); + let mut tests = vec![]; + + foreach_html5lib_test( + src_dir, + "tree-construction", + OsStr::new("dat"), + |path, file| { + let buf = io::BufReader::new(file); + let lines = buf.lines().map(|res| res.ok().expect("couldn't read")); + let data = parse_tests(lines); + + for (i, test) in data.into_iter().enumerate() { + make_test( + &mut tests, + ignores, + path.file_name().unwrap().to_str().unwrap(), + i, + test, + ); + } + }, + ); tests } diff --git a/vendor/ident_case/.cargo-checksum.json b/vendor/ident_case/.cargo-checksum.json new file mode 100644 index 0000000000..12d9f99324 --- /dev/null +++ b/vendor/ident_case/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"86f673c2579eacf6bb82331c1feee5269285c2fadcbce8624632b4b979dd5a04","Cargo.toml":"560eba8d5cf4f2c71cc06ef9145eb8f4c163a616cd6d08b031b1eae3448d8203","LICENSE":"508a77d2e7b51d98adeed32648ad124b7b30241a8e70b2e72c99f92d8e5874d1","README.md":"aaf0fcc62756694c61f26e02c8042a00c19f98c516aa62aa5b4779b5c7956c71","src/lib.rs":"514f0c716fba1e8fbeefc118848655ceafa22fd24787ca28c0e7c2143d5c7175"},"package":"b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"} \ No newline at end of file diff --git a/vendor/ident_case/CHANGELOG.md b/vendor/ident_case/CHANGELOG.md new file mode 100644 index 0000000000..4b89142ef3 --- /dev/null +++ b/vendor/ident_case/CHANGELOG.md @@ -0,0 +1,2 @@ +## v1.0.1 - March 18, 2019 +- Add `LICENSE` file (#3)[https://github.com/TedDriggs/ident_case/issues/3] \ No newline at end of file diff --git a/vendor/bitflags-0.9.1/Cargo.toml b/vendor/ident_case/Cargo.toml similarity index 53% rename from vendor/bitflags-0.9.1/Cargo.toml rename to vendor/ident_case/Cargo.toml index 8ac9adbfc1..b5c457cafa 100644 --- a/vendor/bitflags-0.9.1/Cargo.toml +++ b/vendor/ident_case/Cargo.toml @@ -11,21 +11,13 @@ # will likely look very different (and much more reasonable) [package] -name = "bitflags" -version = "0.9.1" -authors = ["The Rust Project Developers"] -description = "A macro to generate structures which behave like bitflags.\n" -homepage = "https://github.com/rust-lang-nursery/bitflags" -documentation = "https://docs.rs/bitflags" +name = "ident_case" +version = "1.0.1" +authors = ["Ted Driggs "] +description = "Utility for applying case rules to Rust identifiers." +documentation = "https://docs.rs/ident_case/1.0.1" readme = "README.md" -keywords = ["bit", "bitmask", "bitflags"] -categories = ["no-std"] license = "MIT/Apache-2.0" -repository = "https://github.com/rust-lang-nursery/bitflags" - -[features] -example_generated = [] -unstable_testing = [] -default = ["example_generated"] +repository = "https://github.com/TedDriggs/ident_case" [badges.travis-ci] -repository = "rust-lang-nursery/bitflags" +repository = "TedDriggs/ident_case" diff --git a/vendor/ident_case/LICENSE b/vendor/ident_case/LICENSE new file mode 100644 index 0000000000..9cf106272a --- /dev/null +++ b/vendor/ident_case/LICENSE @@ -0,0 +1,19 @@ +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/ident_case/README.md b/vendor/ident_case/README.md new file mode 100644 index 0000000000..395f88a205 --- /dev/null +++ b/vendor/ident_case/README.md @@ -0,0 +1,15 @@ +[![Build Status](https://travis-ci.org/TedDriggs/ident_case.svg?branch=master)](https://travis-ci.org/TedDriggs/ident_case) + +Crate for manipulating case of identifiers in Rust programs. + +# Features +* Supports `snake_case`, `lowercase`, `camelCase`, + `PascalCase`, `SCREAMING_SNAKE_CASE`, and `kebab-case` +* Rename variants, and fields + +# Examples +```rust +assert_eq!("helloWorld", RenameRule::CamelCase.apply_to_field("hello_world")); + +assert_eq!("i_love_serde", RenameRule::SnakeCase.apply_to_variant("ILoveSerde")); +``` \ No newline at end of file diff --git a/vendor/ident_case/src/lib.rs b/vendor/ident_case/src/lib.rs new file mode 100644 index 0000000000..d54d65443c --- /dev/null +++ b/vendor/ident_case/src/lib.rs @@ -0,0 +1,168 @@ +//! Crate for changing case of Rust identifiers. +//! +//! # Features +//! * Supports `snake_case`, `lowercase`, `camelCase`, +//! `PascalCase`, `SCREAMING_SNAKE_CASE`, and `kebab-case` +//! * Rename variants, and fields +//! +//! # Examples +//! ```rust +//! use ident_case::RenameRule; +//! +//! assert_eq!("helloWorld", RenameRule::CamelCase.apply_to_field("hello_world")); +//! +//! assert_eq!("i_love_serde", RenameRule::SnakeCase.apply_to_variant("ILoveSerde")); +//! ``` + +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, 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::ascii::AsciiExt; +use std::str::FromStr; + +use self::RenameRule::*; + +/// A casing rule for renaming Rust identifiers. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum RenameRule { + /// No-op rename rule. + None, + /// Rename direct children to "lowercase" style. + LowerCase, + /// Rename direct children to "PascalCase" style, as typically used for enum variants. + PascalCase, + /// Rename direct children to "camelCase" style. + CamelCase, + /// Rename direct children to "snake_case" style, as commonly used for fields. + SnakeCase, + /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants. + ScreamingSnakeCase, + /// Rename direct children to "kebab-case" style. + KebabCase, +} + +impl RenameRule { + /// Change case of a `PascalCase` variant. + pub fn apply_to_variant>(&self, variant: S) -> String { + + let variant = variant.as_ref(); + match *self { + None | PascalCase => variant.to_owned(), + LowerCase => variant.to_ascii_lowercase(), + CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..], + SnakeCase => { + let mut snake = String::new(); + for (i, ch) in variant.char_indices() { + if i > 0 && ch.is_uppercase() { + snake.push('_'); + } + snake.push(ch.to_ascii_lowercase()); + } + snake + } + ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(), + KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"), + } + } + + /// Change case of a `snake_case` field. + pub fn apply_to_field>(&self, field: S) -> String { + + let field = field.as_ref(); + match *self { + None | LowerCase | SnakeCase => field.to_owned(), + PascalCase => { + let mut pascal = String::new(); + let mut capitalize = true; + for ch in field.chars() { + if ch == '_' { + capitalize = true; + } else if capitalize { + pascal.push(ch.to_ascii_uppercase()); + capitalize = false; + } else { + pascal.push(ch); + } + } + pascal + } + CamelCase => { + let pascal = PascalCase.apply_to_field(field); + pascal[..1].to_ascii_lowercase() + &pascal[1..] + } + ScreamingSnakeCase => field.to_ascii_uppercase(), + KebabCase => field.replace('_', "-"), + } + } +} + +impl FromStr for RenameRule { + type Err = (); + + fn from_str(rename_all_str: &str) -> Result { + match rename_all_str { + "lowercase" => Ok(LowerCase), + "PascalCase" => Ok(PascalCase), + "camelCase" => Ok(CamelCase), + "snake_case" => Ok(SnakeCase), + "SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase), + "kebab-case" => Ok(KebabCase), + _ => Err(()), + } + } +} + +impl Default for RenameRule { + fn default() -> Self { + RenameRule::None + } +} + +#[cfg(test)] +mod tests { + use super::RenameRule::*; + + #[test] + fn rename_variants() { + for &(original, lower, camel, snake, screaming, kebab) in + &[ + ("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome"), + ("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"), + ("A", "a", "a", "a", "A", "a"), + ("Z42", "z42", "z42", "z42", "Z42", "z42"), + ] { + assert_eq!(None.apply_to_variant(original), original); + assert_eq!(LowerCase.apply_to_variant(original), lower); + assert_eq!(PascalCase.apply_to_variant(original), original); + assert_eq!(CamelCase.apply_to_variant(original), camel); + assert_eq!(SnakeCase.apply_to_variant(original), snake); + assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming); + assert_eq!(KebabCase.apply_to_variant(original), kebab); + } + } + + #[test] + fn rename_fields() { + for &(original, pascal, camel, screaming, kebab) in + &[ + ("outcome", "Outcome", "outcome", "OUTCOME", "outcome"), + ("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty"), + ("_leading_under", "LeadingUnder", "leadingUnder", "_LEADING_UNDER", "-leading-under"), + ("double__under", "DoubleUnder", "doubleUnder", "DOUBLE__UNDER", "double--under"), + ("a", "A", "a", "A", "a"), + ("z42", "Z42", "z42", "Z42", "z42"), + ] { + assert_eq!(None.apply_to_field(original), original); + assert_eq!(PascalCase.apply_to_field(original), pascal); + assert_eq!(CamelCase.apply_to_field(original), camel); + assert_eq!(SnakeCase.apply_to_field(original), original); + assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming); + assert_eq!(KebabCase.apply_to_field(original), kebab); + } + } +} \ No newline at end of file diff --git a/vendor/indexmap/.cargo-checksum.json b/vendor/indexmap/.cargo-checksum.json new file mode 100644 index 0000000000..b984a7e2cd --- /dev/null +++ b/vendor/indexmap/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"d9442b75bd8fb879d10d1da75350d1566b3053eb8803065bf4e00cd843f2ff6e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ecc269ef87fd38a1d98e30bfac9ba964a9dbd9315c3770fed98d4d7cb5882055","README.rst":"3ff031666d039af73499c7de94a5e1f990f89156c698d234da2e379723a2143f","benches/bench.rs":"ed5108d81b3cb3806bfc652e745ec0ec353766bdb9537d834606c6cb233bb27e","benches/faststring.rs":"724c5dc83e333c00d28393e346f3feb6a93c64d5c3d6d5a00f680b22b8259c31","src/equivalent.rs":"4d07c0ae8c8ff405fdbb45e6c891158d3fdcfedd47001e4cec090c79b5c56564","src/lib.rs":"483aa0587bd21942988ab094430179b65f80678734c4ac7cf734d10541a75b0e","src/macros.rs":"472c9ec707495e6de60b4e67c1b25f2201bb962fa6672fae32addde2eb4df376","src/map.rs":"83baecdf14c3f93d0fd3b4a1ec7996a11247450b8a713a4605c1484463c50204","src/mutable_keys.rs":"2bf26fb36ad0ccd3c40b0f2cc4e5b8429e6627207f50fca07110a5011880a9dc","src/serde.rs":"16eae1b7fb2d8d0a030e221d180355b967aa6d48fe431a06bec75a182cb97f69","src/set.rs":"b597592bca71b128ba8b06b75d772d39cef9490c0be3dac55d38e090bbbb1e73","src/util.rs":"331f80b48387878caa01ab9cfd43927ea0c15129c6beb755d6b40abc6ada900f","tests/equivalent_trait.rs":"f48ef255e4bc6bc85ed11fd9bee4cc53759efb182e448d315f8d12af1f80b05d","tests/quick.rs":"865be7928ec19dbf58c896bd2a3fd848a756328a429934a9aad5a364298228f0","tests/serde.rs":"48f2a2184c819ffaa5c234ccea9c3bea1c58edf8ad9ada1476eedc179438d07d","tests/tests.rs":"c916ae9c5d08c042b7c3a0447ef3db5a1b9d37b3122fddace4235296a623725b"},"package":"7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"} \ No newline at end of file diff --git a/vendor/indexmap/Cargo.toml b/vendor/indexmap/Cargo.toml new file mode 100644 index 0000000000..c045fd0a5b --- /dev/null +++ b/vendor/indexmap/Cargo.toml @@ -0,0 +1,58 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "indexmap" +version = "1.0.2" +authors = ["bluss", "Josh Stone "] +description = "A hash table with consistent order and fast iteration.\n\nThe indexmap is a hash table where the iteration order of the key-value\npairs is independent of the hash values of the keys. It has the usual\nhash table functionality, it preserves insertion order except after\nremovals, and it allows lookup of its elements by either hash table key\nor numerical index. A corresponding hash set type is also provided.\n\nThis crate was initially published under the name ordermap, but it was renamed to\nindexmap.\n" +documentation = "https://docs.rs/indexmap/" +keywords = ["hashmap"] +categories = ["data-structures"] +license = "Apache-2.0/MIT" +repository = "https://github.com/bluss/indexmap" +[package.metadata.docs.rs] +features = ["serde-1"] + +[package.metadata.release] +no-dev-version = true +[profile.bench] +debug = true + +[lib] +bench = false +[dependencies.serde] +version = "1.0" +optional = true +[dev-dependencies.fnv] +version = "1.0" + +[dev-dependencies.itertools] +version = "0.7.0" + +[dev-dependencies.lazy_static] +version = "1" + +[dev-dependencies.quickcheck] +version = "0.6" +default-features = false + +[dev-dependencies.rand] +version = "0.4" + +[dev-dependencies.serde_test] +version = "1.0.5" + +[features] +serde-1 = ["serde"] +test_debug = [] +test_low_transition_point = [] diff --git a/vendor/indexmap/LICENSE-APACHE b/vendor/indexmap/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/vendor/indexmap/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/itertools-0.7.8/LICENSE-MIT b/vendor/indexmap/LICENSE-MIT similarity index 97% rename from vendor/itertools-0.7.8/LICENSE-MIT rename to vendor/indexmap/LICENSE-MIT index 9203baa055..8b8181068b 100644 --- a/vendor/itertools-0.7.8/LICENSE-MIT +++ b/vendor/indexmap/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2015 +Copyright (c) 2016--2017 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/vendor/indexmap/README.rst b/vendor/indexmap/README.rst new file mode 100644 index 0000000000..bde106098f --- /dev/null +++ b/vendor/indexmap/README.rst @@ -0,0 +1,287 @@ +indexmap +======== + +|build_status|_ |crates|_ |docs|_ |rustc|_ + +.. |crates| image:: https://img.shields.io/crates/v/indexmap.svg +.. _crates: https://crates.io/crates/indexmap + +.. |build_status| image:: https://travis-ci.org/bluss/indexmap.svg +.. _build_status: https://travis-ci.org/bluss/indexmap + +.. |docs| image:: https://docs.rs/indexmap/badge.svg +.. _docs: https://docs.rs/indexmap + +.. |rustc| image:: https://img.shields.io/badge/rust-1.18%2B-orange.svg +.. _rustc: https://img.shields.io/badge/rust-1.18%2B-orange.svg + +A safe, pure-Rust hash table which preserves insertion order. + +This crate implements compact map and set data-structures, +where the iteration order of the keys is independent from their hash or +value. It preserves insertion order (except after removals), and it +allows lookup of entries by either hash table key or numerical index. + +Note: this crate was originally released under the name ``ordermap``, +but it was renamed to ``indexmap`` to better reflect its features. + +Background +========== + +This was inspired by Python 3.6's new dict implementation (which remembers +the insertion order and is fast to iterate, and is compact in memory). + +Some of those features were translated to Rust, and some were not. The result +was indexmap, a hash table that has following properties: + +- Order is **independent of hash function** and hash values of keys. +- Fast to iterate. +- Indexed in compact space. +- Preserves insertion order **as long** as you don't call ``.remove()``. +- Uses robin hood hashing just like Rust's libstd ``HashMap``. + + - It's the usual backwards shift deletion, but only on the index vector, so + it's cheaper because it's moving less memory around. + +Does not implement (Yet) +------------------------ + +- ``.reserve()`` exists but does not have a complete implementation + +Performance +----------- + +``IndexMap`` derives a couple of performance facts directly from how it is constructed, +which is roughly: + + Two vectors, the first, sparse, with hashes and key-value indices, and the + second, dense, the key-value pairs. + +- Iteration is very fast since it is on the dense key-values. +- Removal is fast since it moves memory areas only in the first vector, + and uses a single swap in the second vector. +- Lookup is fast-ish because the hashes and indices are densely stored. + Lookup also is slow-ish since hashes and key-value pairs are stored in + separate places. (Visible when cpu caches size is limiting.) + +- In practice, ``IndexMap`` has been tested out as the hashmap in rustc in PR45282_ and + the performance was roughly on par across the whole workload. +- If you want the properties of ``IndexMap``, or its strongest performance points + fits your workload, it might be the best hash table implementation. + +.. _PR45282: https://github.com/rust-lang/rust/pull/45282 + +Interesting Features +-------------------- + +- Insertion order is preserved (``.swap_remove()`` perturbs the order, like the method name says). +- Implements ``.pop() -> Option<(K, V)>`` in O(1) time. +- ``IndexMap::new()`` is empty and uses no allocation until you insert something. +- Lookup key-value pairs by index and vice versa. +- No ``unsafe``. +- Supports ``IndexMut``. + + +Where to go from here? +---------------------- + +- Ideas and PRs for how to implement insertion-order preserving remove (for example tombstones) + are welcome. The plan is to split the crate into two hash table implementations + a) the current compact index space version and b) the full insertion order version. + + +Ideas that we already did +------------------------- + +- It can be an *indexable* ordered map in the current fashion + (This was implemented in 0.2.0, for potential use as a graph datastructure). + +- Idea for more cache efficient lookup (This was implemented in 0.1.2). + + Current ``indices: Vec``. ``Pos`` is interpreted as ``(u32, u32)`` more + or less when ``.raw_capacity()`` fits in 32 bits. ``Pos`` then stores both the lower + half of the hash and the entry index. + This means that the hash values in ``Bucket`` don't need to be accessed + while scanning for an entry. + + +Recent Changes +============== + +- 1.0.2 + + - The new methods ``IndexMap::insert_full`` and ``IndexSet::insert_full`` are + both like ``insert`` with the index included in the return value. + + - The new method ``Entry::and_modify`` can be used to modify occupied + entries, matching the new methods of ``std`` maps in Rust 1.26. + + - The new method ``Entry::or_default`` inserts a default value in unoccupied + entries, matching the new methods of ``std`` maps in Rust 1.28. + +- 1.0.1 + + - Document Rust version policy for the crate (see rustdoc) + +- 1.0.0 + + - This is the 1.0 release for ``indexmap``! (the crate and datastructure + formerly known as “ordermap”) + - ``OccupiedEntry::insert`` changed its signature, to use ``&mut self`` for + the method receiver, matching the equivalent method for a standard + ``HashMap``. Thanks to @dtolnay for finding this bug. + - The deprecated old names from ordermap were removed: ``OrderMap``, + ``OrderSet``, ``ordermap!{}``, ``orderset!{}``. Use the new ``IndexMap`` + etc names instead. + +- 0.4.1 + + - Renamed crate to ``indexmap``; the ``ordermap`` crate is now deprecated + and the types ``OrderMap/Set`` now have a deprecation notice. + +- 0.4.0 + + - This is the last release series for this ``ordermap`` under that name, + because the crate is **going to be renamed** to ``indexmap`` (with types + ``IndexMap``, ``IndexSet``) and no change in functionality! + - The map and its associated structs moved into the ``map`` submodule of the + crate, so that the map and set are symmetric + + + The iterators, ``Entry`` and other structs are now under ``ordermap::map::`` + + - Internally refactored ``OrderMap`` so that all the main algorithms + (insertion, lookup, removal etc) that don't use the ``S`` parameter (the + hasher) are compiled without depending on ``S``, which reduces generics bloat. + + - ``Entry`` no longer has a type parameter ``S``, which is just like + the standard ``HashMap``'s entry. + + - Minimum Rust version requirement increased to Rust 1.18 + +- 0.3.5 + + - Documentation improvements + +- 0.3.4 + + - The ``.retain()`` methods for ``OrderMap`` and ``OrderSet`` now + traverse the elements in order, and the retained elements **keep their order** + - Added new methods ``.sort_by()``, ``.sort_keys()`` to ``OrderMap`` and + ``.sort_by()``, ``.sort()`` to ``OrderSet``. These methods allow you to + sort the maps in place efficiently. + +- 0.3.3 + + - Document insertion behaviour better by @lucab + - Updated dependences (no feature changes) by @ignatenkobrain + +- 0.3.2 + + - Add ``OrderSet`` by @cuviper! + - ``OrderMap::drain`` is now (too) a double ended iterator. + +- 0.3.1 + + - In all ordermap iterators, forward the ``collect`` method to the underlying + iterator as well. + - Add crates.io categories. + +- 0.3.0 + + - The methods ``get_pair``, ``get_pair_index`` were both replaced by + ``get_full`` (and the same for the mutable case). + - Method ``swap_remove_pair`` replaced by ``swap_remove_full``. + - Add trait ``MutableKeys`` for opt-in mutable key access. Mutable key access + is only possible through the methods of this extension trait. + - Add new trait ``Equivalent`` for key equivalence. This extends the + ``Borrow`` trait mechanism for ``OrderMap::get`` in a backwards compatible + way, just some minor type inference related issues may become apparent. + See `#10`__ for more information. + - Implement ``Extend<(&K, &V)>`` by @xfix. + +__ https://github.com/bluss/ordermap/pull/10 + +- 0.2.13 + + - Fix deserialization to support custom hashers by @Techcable. + - Add methods ``.index()`` on the entry types by @garro95. + +- 0.2.12 + + - Add methods ``.with_hasher()``, ``.hasher()``. + +- 0.2.11 + + - Support ``ExactSizeIterator`` for the iterators. By @Binero. + - Use ``Box<[Pos]>`` internally, saving a word in the ``OrderMap`` struct. + - Serde support, with crate feature ``"serde-1"``. By @xfix. + +- 0.2.10 + + - Add iterator ``.drain(..)`` by @stevej. + +- 0.2.9 + + - Add method ``.is_empty()`` by @overvenus. + - Implement ``PartialEq, Eq`` by @overvenus. + - Add method ``.sorted_by()``. + +- 0.2.8 + + - Add iterators ``.values()`` and ``.values_mut()``. + - Fix compatibility with 32-bit platforms. + +- 0.2.7 + + - Add ``.retain()``. + +- 0.2.6 + + - Add ``OccupiedEntry::remove_entry`` and other minor entry methods, + so that it now has all the features of ``HashMap``'s entries. + +- 0.2.5 + + - Improved ``.pop()`` slightly. + +- 0.2.4 + + - Improved performance of ``.insert()`` (`#3`__) by @pczarn. + +__ https://github.com/bluss/ordermap/pull/3 + +- 0.2.3 + + - Generalize ``Entry`` for now, so that it works on hashmaps with non-default + hasher. However, there's a lingering compat issue since libstd ``HashMap`` + does not parameterize its entries by the hasher (``S`` typarm). + - Special case some iterator methods like ``.nth()``. + +- 0.2.2 + + - Disable the verbose ``Debug`` impl by default. + +- 0.2.1 + + - Fix doc links and clarify docs. + +- 0.2.0 + + - Add more ``HashMap`` methods & compat with its API. + - Experimental support for ``.entry()`` (the simplest parts of the API). + - Add ``.reserve()`` (placeholder impl). + - Add ``.remove()`` as synonym for ``.swap_remove()``. + - Changed ``.insert()`` to swap value if the entry already exists, and + return ``Option``. + - Experimental support as an *indexed* hash map! Added methods + ``.get_index()``, ``.get_index_mut()``, ``.swap_remove_index()``, + ``.get_pair_index()``, ``.get_pair_index_mut()``. + +- 0.1.2 + + - Implement the 32/32 split idea for ``Pos`` which improves cache utilization + and lookup performance. + +- 0.1.1 + + - Initial release. diff --git a/vendor/indexmap/benches/bench.rs b/vendor/indexmap/benches/bench.rs new file mode 100644 index 0000000000..b3e9915f13 --- /dev/null +++ b/vendor/indexmap/benches/bench.rs @@ -0,0 +1,745 @@ +#![feature(test)] +extern crate test; +extern crate rand; +extern crate fnv; +#[macro_use] +extern crate lazy_static; + +use std::hash::Hash; +use fnv::FnvHasher; +use std::hash::BuildHasherDefault; +type FnvBuilder = BuildHasherDefault; + +use test::Bencher; +use test::black_box; + +extern crate indexmap; + +use indexmap::IndexMap; + +use std::collections::HashMap; +use std::iter::FromIterator; + +use rand::{weak_rng, Rng}; + +#[bench] +fn new_hashmap(b: &mut Bencher) { + b.iter(|| { + HashMap::::new() + }); +} + +#[bench] +fn new_orderedmap(b: &mut Bencher) { + b.iter(|| { + IndexMap::::new() + }); +} + +#[bench] +fn with_capacity_10e5_hashmap(b: &mut Bencher) { + b.iter(|| { + HashMap::::with_capacity(10_000) + }); +} + +#[bench] +fn with_capacity_10e5_orderedmap(b: &mut Bencher) { + b.iter(|| { + IndexMap::::with_capacity(10_000) + }); +} + +#[bench] +fn insert_hashmap_10_000(b: &mut Bencher) { + let c = 10_000; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for x in 0..c { + map.insert(x, ()); + } + map + }); +} + +#[bench] +fn insert_orderedmap_10_000(b: &mut Bencher) { + let c = 10_000; + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for x in 0..c { + map.insert(x, ()); + } + map + }); +} + +#[bench] +fn insert_hashmap_string_10_000(b: &mut Bencher) { + let c = 10_000; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for x in 0..c { + map.insert(x.to_string(), ()); + } + map + }); +} + +#[bench] +fn insert_orderedmap_string_10_000(b: &mut Bencher) { + let c = 10_000; + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for x in 0..c { + map.insert(x.to_string(), ()); + } + map + }); +} + +#[bench] +fn insert_hashmap_str_10_000(b: &mut Bencher) { + let c = 10_000; + let ss = Vec::from_iter((0..c).map(|x| x.to_string())); + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for key in &ss { + map.insert(&key[..], ()); + } + map + }); +} + +#[bench] +fn insert_orderedmap_str_10_000(b: &mut Bencher) { + let c = 10_000; + let ss = Vec::from_iter((0..c).map(|x| x.to_string())); + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for key in &ss { + map.insert(&key[..], ()); + } + map + }); +} + +#[bench] +fn insert_hashmap_int_bigvalue_10_000(b: &mut Bencher) { + let c = 10_000; + let value = [0u64; 10]; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for i in 0..c { + map.insert(i, value); + } + map + }); +} + +#[bench] +fn insert_orderedmap_int_bigvalue_10_000(b: &mut Bencher) { + let c = 10_000; + let value = [0u64; 10]; + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for i in 0..c { + map.insert(i, value); + } + map + }); +} + +#[bench] +fn insert_hashmap_100_000(b: &mut Bencher) { + let c = 100_000; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for x in 0..c { + map.insert(x, ()); + } + map + }); +} + +#[bench] +fn insert_orderedmap_100_000(b: &mut Bencher) { + let c = 100_000; + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for x in 0..c { + map.insert(x, ()); + } + map + }); +} + +#[bench] +fn insert_hashmap_150(b: &mut Bencher) { + let c = 150; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for x in 0..c { + map.insert(x, ()); + } + map + }); +} + +#[bench] +fn insert_orderedmap_150(b: &mut Bencher) { + let c = 150; + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for x in 0..c { + map.insert(x, ()); + } + map + }); +} + +#[bench] +fn entry_hashmap_150(b: &mut Bencher) { + let c = 150; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for x in 0..c { + map.entry(x).or_insert(()); + } + map + }); +} + +#[bench] +fn entry_orderedmap_150(b: &mut Bencher) { + let c = 150; + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for x in 0..c { + map.entry(x).or_insert(()); + } + map + }); +} + +#[bench] +fn iter_sum_hashmap_10_000(b: &mut Bencher) { + let c = 10_000; + let mut map = HashMap::with_capacity(c); + let len = c - c/10; + for x in 0..len { + map.insert(x, ()); + } + assert_eq!(map.len(), len); + b.iter(|| { + map.keys().sum::() + }); +} + +#[bench] +fn iter_sum_orderedmap_10_000(b: &mut Bencher) { + let c = 10_000; + let mut map = IndexMap::with_capacity(c); + let len = c - c/10; + for x in 0..len { + map.insert(x, ()); + } + assert_eq!(map.len(), len); + b.iter(|| { + map.keys().sum::() + }); +} + +#[bench] +fn iter_black_box_hashmap_10_000(b: &mut Bencher) { + let c = 10_000; + let mut map = HashMap::with_capacity(c); + let len = c - c/10; + for x in 0..len { + map.insert(x, ()); + } + assert_eq!(map.len(), len); + b.iter(|| { + for &key in map.keys() { + black_box(key); + } + }); +} + +#[bench] +fn iter_black_box_orderedmap_10_000(b: &mut Bencher) { + let c = 10_000; + let mut map = IndexMap::with_capacity(c); + let len = c - c/10; + for x in 0..len { + map.insert(x, ()); + } + assert_eq!(map.len(), len); + b.iter(|| { + for &key in map.keys() { + black_box(key); + } + }); +} + +fn shuffled_keys(iter: I) -> Vec + where I: IntoIterator +{ + let mut v = Vec::from_iter(iter); + let mut rng = weak_rng(); + rng.shuffle(&mut v); + v +} + +#[bench] +fn lookup_hashmap_10_000_exist(b: &mut Bencher) { + let c = 10_000; + let mut map = HashMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(key, 1); + } + b.iter(|| { + let mut found = 0; + for key in 5000..c { + found += map.get(&key).is_some() as i32; + } + found + }); +} + +#[bench] +fn lookup_hashmap_10_000_noexist(b: &mut Bencher) { + let c = 10_000; + let mut map = HashMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(key, 1); + } + b.iter(|| { + let mut found = 0; + for key in c..15000 { + found += map.get(&key).is_some() as i32; + } + found + }); +} + +#[bench] +fn lookup_orderedmap_10_000_exist(b: &mut Bencher) { + let c = 10_000; + let mut map = IndexMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(key, 1); + } + b.iter(|| { + let mut found = 0; + for key in 5000..c { + found += map.get(&key).is_some() as i32; + } + found + }); +} + +#[bench] +fn lookup_orderedmap_10_000_noexist(b: &mut Bencher) { + let c = 10_000; + let mut map = IndexMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(key, 1); + } + b.iter(|| { + let mut found = 0; + for key in c..15000 { + found += map.get(&key).is_some() as i32; + } + found + }); +} + +// number of items to look up +const LOOKUP_MAP_SIZE: u32 = 100_000_u32; +const LOOKUP_SAMPLE_SIZE: u32 = 5000; +const SORT_MAP_SIZE: usize = 10_000; + + +// use lazy_static so that comparison benchmarks use the exact same inputs +lazy_static! { + static ref KEYS: Vec = { + shuffled_keys(0..LOOKUP_MAP_SIZE) + }; +} + +lazy_static! { + static ref HMAP_100K: HashMap = { + let c = LOOKUP_MAP_SIZE; + let mut map = HashMap::with_capacity(c as usize); + let keys = &*KEYS; + for &key in keys { + map.insert(key, key); + } + map + }; +} + +lazy_static! { + static ref OMAP_100K: IndexMap = { + let c = LOOKUP_MAP_SIZE; + let mut map = IndexMap::with_capacity(c as usize); + let keys = &*KEYS; + for &key in keys { + map.insert(key, key); + } + map + }; +} + +lazy_static! { + static ref OMAP_SORT_U32: IndexMap = { + let mut map = IndexMap::with_capacity(SORT_MAP_SIZE); + for &key in &KEYS[..SORT_MAP_SIZE] { + map.insert(key, key); + } + map + }; +} +lazy_static! { + static ref OMAP_SORT_S: IndexMap = { + let mut map = IndexMap::with_capacity(SORT_MAP_SIZE); + for &key in &KEYS[..SORT_MAP_SIZE] { + map.insert(format!("{:^16x}", &key), String::new()); + } + map + }; +} + +#[bench] +fn lookup_hashmap_100_000_multi(b: &mut Bencher) { + let map = &*HMAP_100K; + b.iter(|| { + let mut found = 0; + for key in 0..LOOKUP_SAMPLE_SIZE { + found += map.get(&key).is_some() as u32; + } + found + }); +} + + +#[bench] +fn lookup_ordermap_100_000_multi(b: &mut Bencher) { + let map = &*OMAP_100K; + b.iter(|| { + let mut found = 0; + for key in 0..LOOKUP_SAMPLE_SIZE { + found += map.get(&key).is_some() as u32; + } + found + }); +} + +// inorder: Test looking up keys in the same order as they were inserted +#[bench] +fn lookup_hashmap_100_000_inorder_multi(b: &mut Bencher) { + let map = &*HMAP_100K; + let keys = &*KEYS; + b.iter(|| { + let mut found = 0; + for key in &keys[0..LOOKUP_SAMPLE_SIZE as usize] { + found += map.get(key).is_some() as u32; + } + found + }); +} + + +#[bench] +fn lookup_ordermap_100_000_inorder_multi(b: &mut Bencher) { + let map = &*OMAP_100K; + let keys = &*KEYS; + b.iter(|| { + let mut found = 0; + for key in &keys[0..LOOKUP_SAMPLE_SIZE as usize] { + found += map.get(key).is_some() as u32; + } + found + }); +} + +#[bench] +fn lookup_hashmap_100_000_single(b: &mut Bencher) { + let map = &*HMAP_100K; + let mut iter = (0..LOOKUP_MAP_SIZE + LOOKUP_SAMPLE_SIZE).cycle(); + b.iter(|| { + let key = iter.next().unwrap(); + map.get(&key).is_some() + }); +} + + +#[bench] +fn lookup_ordermap_100_000_single(b: &mut Bencher) { + let map = &*OMAP_100K; + let mut iter = (0..LOOKUP_MAP_SIZE + LOOKUP_SAMPLE_SIZE).cycle(); + b.iter(|| { + let key = iter.next().unwrap(); + map.get(&key).is_some() + }); +} + +const GROW_SIZE: usize = 100_000; +type GrowKey = u32; + +// Test grow/resize without preallocation +#[bench] +fn grow_fnv_hashmap_100_000(b: &mut Bencher) { + b.iter(|| { + let mut map: HashMap<_, _, FnvBuilder> = HashMap::default(); + for x in 0..GROW_SIZE { + map.insert(x as GrowKey, x as GrowKey); + } + map + }); +} + +#[bench] +fn grow_fnv_ordermap_100_000(b: &mut Bencher) { + b.iter(|| { + let mut map: IndexMap<_, _, FnvBuilder> = IndexMap::default(); + for x in 0..GROW_SIZE { + map.insert(x as GrowKey, x as GrowKey); + } + map + }); +} + + +const MERGE: u64 = 10_000; +#[bench] +fn hashmap_merge_simple(b: &mut Bencher) { + let first_map: HashMap = (0..MERGE).map(|i| (i, ())).collect(); + let second_map: HashMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); + b.iter(|| { + let mut merged = first_map.clone(); + merged.extend(second_map.iter().map(|(&k, &v)| (k, v))); + merged + }); +} + +#[bench] +fn hashmap_merge_shuffle(b: &mut Bencher) { + let first_map: HashMap = (0..MERGE).map(|i| (i, ())).collect(); + let second_map: HashMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); + let mut v = Vec::new(); + let mut rng = weak_rng(); + b.iter(|| { + let mut merged = first_map.clone(); + v.extend(second_map.iter().map(|(&k, &v)| (k, v))); + rng.shuffle(&mut v); + merged.extend(v.drain(..)); + + merged + }); +} + +#[bench] +fn ordermap_merge_simple(b: &mut Bencher) { + let first_map: IndexMap = (0..MERGE).map(|i| (i, ())).collect(); + let second_map: IndexMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); + b.iter(|| { + let mut merged = first_map.clone(); + merged.extend(second_map.iter().map(|(&k, &v)| (k, v))); + merged + }); +} + +#[bench] +fn ordermap_merge_shuffle(b: &mut Bencher) { + let first_map: IndexMap = (0..MERGE).map(|i| (i, ())).collect(); + let second_map: IndexMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); + let mut v = Vec::new(); + let mut rng = weak_rng(); + b.iter(|| { + let mut merged = first_map.clone(); + v.extend(second_map.iter().map(|(&k, &v)| (k, v))); + rng.shuffle(&mut v); + merged.extend(v.drain(..)); + + merged + }); +} + +#[bench] +fn remove_ordermap_100_000(b: &mut Bencher) { + let map = OMAP_100K.clone(); + let mut keys = Vec::from_iter(map.keys().cloned()); + weak_rng().shuffle(&mut keys); + + b.iter(|| { + let mut map = map.clone(); + for key in &keys { + map.remove(key).is_some(); + } + assert_eq!(map.len(), 0); + map + }); +} + +#[bench] +fn pop_ordermap_100_000(b: &mut Bencher) { + let map = OMAP_100K.clone(); + + b.iter(|| { + let mut map = map.clone(); + while map.len() > 0 { + map.pop(); + } + assert_eq!(map.len(), 0); + map + }); +} + +#[bench] +fn few_retain_ordermap_100_000(b: &mut Bencher) { + let map = OMAP_100K.clone(); + + b.iter(|| { + let mut map = map.clone(); + map.retain(|k, _| *k % 7 == 0); + map + }); +} + +#[bench] +fn few_retain_hashmap_100_000(b: &mut Bencher) { + let map = HMAP_100K.clone(); + + b.iter(|| { + let mut map = map.clone(); + map.retain(|k, _| *k % 7 == 0); + map + }); +} + +#[bench] +fn half_retain_ordermap_100_000(b: &mut Bencher) { + let map = OMAP_100K.clone(); + + b.iter(|| { + let mut map = map.clone(); + map.retain(|k, _| *k % 2 == 0); + map + }); +} + +#[bench] +fn half_retain_hashmap_100_000(b: &mut Bencher) { + let map = HMAP_100K.clone(); + + b.iter(|| { + let mut map = map.clone(); + map.retain(|k, _| *k % 2 == 0); + map + }); +} + +#[bench] +fn many_retain_ordermap_100_000(b: &mut Bencher) { + let map = OMAP_100K.clone(); + + b.iter(|| { + let mut map = map.clone(); + map.retain(|k, _| *k % 100 != 0); + map + }); +} + +#[bench] +fn many_retain_hashmap_100_000(b: &mut Bencher) { + let map = HMAP_100K.clone(); + + b.iter(|| { + let mut map = map.clone(); + map.retain(|k, _| *k % 100 != 0); + map + }); +} + + +// simple sort impl for comparison +pub fn simple_sort(m: &mut IndexMap) { + let mut ordered: Vec<_> = m.drain(..).collect(); + ordered.sort_by(|left, right| left.0.cmp(&right.0)); + m.extend(ordered); +} + + +#[bench] +fn ordermap_sort_s(b: &mut Bencher) { + let map = OMAP_SORT_S.clone(); + + // there's a map clone there, but it's still useful to profile this + b.iter(|| { + let mut map = map.clone(); + map.sort_keys(); + map + }); +} + +#[bench] +fn ordermap_simple_sort_s(b: &mut Bencher) { + let map = OMAP_SORT_S.clone(); + + // there's a map clone there, but it's still useful to profile this + b.iter(|| { + let mut map = map.clone(); + simple_sort(&mut map); + map + }); +} + +#[bench] +fn ordermap_sort_u32(b: &mut Bencher) { + let map = OMAP_SORT_U32.clone(); + + // there's a map clone there, but it's still useful to profile this + b.iter(|| { + let mut map = map.clone(); + map.sort_keys(); + map + }); +} + +#[bench] +fn ordermap_simple_sort_u32(b: &mut Bencher) { + let map = OMAP_SORT_U32.clone(); + + // there's a map clone there, but it's still useful to profile this + b.iter(|| { + let mut map = map.clone(); + simple_sort(&mut map); + map + }); +} + +// measure the fixed overhead of cloning in sort benchmarks +#[bench] +fn ordermap_clone_for_sort_s(b: &mut Bencher) { + let map = OMAP_SORT_S.clone(); + + b.iter(|| { + map.clone() + }); +} + +#[bench] +fn ordermap_clone_for_sort_u32(b: &mut Bencher) { + let map = OMAP_SORT_U32.clone(); + + b.iter(|| { + map.clone() + }); +} + diff --git a/vendor/indexmap/benches/faststring.rs b/vendor/indexmap/benches/faststring.rs new file mode 100644 index 0000000000..65e780134d --- /dev/null +++ b/vendor/indexmap/benches/faststring.rs @@ -0,0 +1,183 @@ +#![feature(test)] +extern crate test; +extern crate rand; +extern crate lazy_static; + +use test::Bencher; + +extern crate indexmap; + +use indexmap::IndexMap; + +use std::collections::HashMap; +use std::iter::FromIterator; + +use rand::{weak_rng, Rng}; + +use std::hash::{Hash, Hasher}; + +use std::borrow::Borrow; +use std::ops::Deref; +use std::mem; + +#[derive(PartialEq, Eq, Copy, Clone)] +pub struct OneShot(pub T); + +impl Hash for OneShot +{ + fn hash(&self, h: &mut H) { + h.write(self.0.as_bytes()) + } +} + +impl<'a, S> From<&'a S> for &'a OneShot + where S: AsRef +{ + fn from(s: &'a S) -> Self { + let s: &str = s.as_ref(); + unsafe { + mem::transmute(s) + } + } +} + +impl Hash for OneShot +{ + fn hash(&self, h: &mut H) { + h.write(self.0.as_bytes()) + } +} + +impl Borrow> for OneShot +{ + fn borrow(&self) -> &OneShot { + <&OneShot>::from(&self.0) + } +} + +impl Deref for OneShot +{ + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + + +fn shuffled_keys(iter: I) -> Vec + where I: IntoIterator +{ + let mut v = Vec::from_iter(iter); + let mut rng = weak_rng(); + rng.shuffle(&mut v); + v +} + + +#[bench] +fn insert_hashmap_string_10_000(b: &mut Bencher) { + let c = 10_000; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for x in 0..c { + map.insert(x.to_string(), ()); + } + map + }); +} + +#[bench] +fn insert_hashmap_string_oneshot_10_000(b: &mut Bencher) { + let c = 10_000; + b.iter(|| { + let mut map = HashMap::with_capacity(c); + for x in 0..c { + map.insert(OneShot(x.to_string()), ()); + } + map + }); +} + +#[bench] +fn insert_orderedmap_string_10_000(b: &mut Bencher) { + let c = 10_000; + b.iter(|| { + let mut map = IndexMap::with_capacity(c); + for x in 0..c { + map.insert(x.to_string(), ()); + } + map + }); +} + +#[bench] +fn lookup_hashmap_10_000_exist_string(b: &mut Bencher) { + let c = 10_000; + let mut map = HashMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(key.to_string(), 1); + } + let lookups = (5000..c).map(|x| x.to_string()).collect::>(); + b.iter(|| { + let mut found = 0; + for key in &lookups { + found += map.get(key).is_some() as i32; + } + found + }); +} + +#[bench] +fn lookup_hashmap_10_000_exist_string_oneshot(b: &mut Bencher) { + let c = 10_000; + let mut map = HashMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(OneShot(key.to_string()), 1); + } + let lookups = (5000..c).map(|x| OneShot(x.to_string())).collect::>(); + b.iter(|| { + let mut found = 0; + for key in &lookups { + found += map.get(key).is_some() as i32; + } + found + }); +} + +#[bench] +fn lookup_ordermap_10_000_exist_string(b: &mut Bencher) { + let c = 10_000; + let mut map = IndexMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(key.to_string(), 1); + } + let lookups = (5000..c).map(|x| x.to_string()).collect::>(); + b.iter(|| { + let mut found = 0; + for key in &lookups { + found += map.get(key).is_some() as i32; + } + found + }); +} + +#[bench] +fn lookup_ordermap_10_000_exist_string_oneshot(b: &mut Bencher) { + let c = 10_000; + let mut map = IndexMap::with_capacity(c); + let keys = shuffled_keys(0..c); + for &key in &keys { + map.insert(OneShot(key.to_string()), 1); + } + let lookups = (5000..c).map(|x| OneShot(x.to_string())).collect::>(); + b.iter(|| { + let mut found = 0; + for key in &lookups { + found += map.get(key).is_some() as i32; + } + found + }); +} diff --git a/vendor/indexmap/src/equivalent.rs b/vendor/indexmap/src/equivalent.rs new file mode 100644 index 0000000000..d72b2ef3a2 --- /dev/null +++ b/vendor/indexmap/src/equivalent.rs @@ -0,0 +1,27 @@ + +use std::borrow::Borrow; + +/// Key equivalence trait. +/// +/// This trait allows hash table lookup to be customized. +/// It has one blanket implementation that uses the regular `Borrow` solution, +/// just like `HashMap` and `BTreeMap` do, so that you can pass `&str` to lookup +/// into a map with `String` keys and so on. +/// +/// # Contract +/// +/// The implementor **must** hash like `K`, if it is hashable. +pub trait Equivalent { + /// Compare self to `key` and return `true` if they are equal. + fn equivalent(&self, key: &K) -> bool; +} + +impl Equivalent for Q + where Q: Eq, + K: Borrow, +{ + #[inline] + fn equivalent(&self, key: &K) -> bool { + *self == *key.borrow() + } +} diff --git a/vendor/indexmap/src/lib.rs b/vendor/indexmap/src/lib.rs new file mode 100644 index 0000000000..1a0655e3f6 --- /dev/null +++ b/vendor/indexmap/src/lib.rs @@ -0,0 +1,79 @@ + +#![deny(unsafe_code)] +#![doc(html_root_url = "https://docs.rs/indexmap/1/")] + +//! [`IndexMap`] is a hash table where the iteration order of the key-value +//! pairs is independent of the hash values of the keys. +//! +//! [`IndexSet`] is a corresponding hash set using the same implementation and +//! with similar properties. +//! +//! [`IndexMap`]: map/struct.IndexMap.html +//! [`IndexSet`]: set/struct.IndexSet.html +//! +//! +//! ## Rust Version +//! +//! This version of indexmap requires Rust 1.18 or later. +//! +//! The indexmap 1.x release series will use a carefully considered version +//! upgrade policy, where in a later 1.x version, we will raise the minimum +//! required Rust version. + +#[macro_use] +mod macros; +#[cfg(feature = "serde-1")] +mod serde; +mod util; +mod equivalent; +mod mutable_keys; + +pub mod set; +pub mod map; + +pub use equivalent::Equivalent; +pub use map::IndexMap; +pub use set::IndexSet; + +// shared private items + +/// Hash value newtype. Not larger than usize, since anything larger +/// isn't used for selecting position anyway. +#[derive(Copy, Debug)] +struct HashValue(usize); + +impl HashValue { + #[inline(always)] + fn get(self) -> usize { self.0 } +} + +impl Clone for HashValue { + #[inline] + fn clone(&self) -> Self { *self } +} +impl PartialEq for HashValue { + #[inline] + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } +} + +#[derive(Copy, Clone, Debug)] +struct Bucket { + hash: HashValue, + key: K, + value: V, +} + +impl Bucket { + // field accessors -- used for `f` instead of closures in `.map(f)` + fn key_ref(&self) -> &K { &self.key } + fn value_ref(&self) -> &V { &self.value } + fn value_mut(&mut self) -> &mut V { &mut self.value } + fn key(self) -> K { self.key } + fn key_value(self) -> (K, V) { (self.key, self.value) } + fn refs(&self) -> (&K, &V) { (&self.key, &self.value) } + fn ref_mut(&mut self) -> (&K, &mut V) { (&self.key, &mut self.value) } + fn muts(&mut self) -> (&mut K, &mut V) { (&mut self.key, &mut self.value) } +} + diff --git a/vendor/indexmap/src/macros.rs b/vendor/indexmap/src/macros.rs new file mode 100644 index 0000000000..b8c6f9b1fc --- /dev/null +++ b/vendor/indexmap/src/macros.rs @@ -0,0 +1,122 @@ + +#[macro_export] +/// Create an `IndexMap` from a list of key-value pairs +/// +/// ## Example +/// +/// ``` +/// #[macro_use] extern crate indexmap; +/// # fn main() { +/// +/// let map = indexmap!{ +/// "a" => 1, +/// "b" => 2, +/// }; +/// assert_eq!(map["a"], 1); +/// assert_eq!(map["b"], 2); +/// assert_eq!(map.get("c"), None); +/// +/// // "a" is the first key +/// assert_eq!(map.keys().next(), Some(&"a")); +/// # } +/// ``` +macro_rules! indexmap { + (@single $($x:tt)*) => (()); + (@count $($rest:expr),*) => (<[()]>::len(&[$(indexmap!(@single $rest)),*])); + + ($($key:expr => $value:expr,)+) => { indexmap!($($key => $value),+) }; + ($($key:expr => $value:expr),*) => { + { + let _cap = indexmap!(@count $($key),*); + let mut _map = $crate::IndexMap::with_capacity(_cap); + $( + _map.insert($key, $value); + )* + _map + } + }; +} + +#[macro_export] +/// Create an `IndexSet` from a list of values +/// +/// ## Example +/// +/// ``` +/// #[macro_use] extern crate indexmap; +/// # fn main() { +/// +/// let set = indexset!{ +/// "a", +/// "b", +/// }; +/// assert!(set.contains("a")); +/// assert!(set.contains("b")); +/// assert!(!set.contains("c")); +/// +/// // "a" is the first value +/// assert_eq!(set.iter().next(), Some(&"a")); +/// # } +/// ``` +macro_rules! indexset { + (@single $($x:tt)*) => (()); + (@count $($rest:expr),*) => (<[()]>::len(&[$(indexset!(@single $rest)),*])); + + ($($value:expr,)+) => { indexset!($($value),+) }; + ($($value:expr),*) => { + { + let _cap = indexset!(@count $($value),*); + let mut _set = $crate::IndexSet::with_capacity(_cap); + $( + _set.insert($value); + )* + _set + } + }; +} + +// generate all the Iterator methods by just forwarding to the underlying +// self.iter and mapping its element. +macro_rules! iterator_methods { + // $map_elt is the mapping function from the underlying iterator's element + // same mapping function for both options and iterators + ($map_elt:expr) => { + fn next(&mut self) -> Option { + self.iter.next().map($map_elt) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn count(self) -> usize { + self.iter.len() + } + + fn nth(&mut self, n: usize) -> Option { + self.iter.nth(n).map($map_elt) + } + + fn last(mut self) -> Option { + self.next_back() + } + + fn collect(self) -> C + where C: FromIterator + { + // NB: forwarding this directly to standard iterators will + // allow it to leverage unstable traits like `TrustedLen`. + self.iter.map($map_elt).collect() + } + } +} + +macro_rules! double_ended_iterator_methods { + // $map_elt is the mapping function from the underlying iterator's element + // same mapping function for both options and iterators + ($map_elt:expr) => { + fn next_back(&mut self) -> Option { + self.iter.next_back().map($map_elt) + } + } +} diff --git a/vendor/indexmap/src/map.rs b/vendor/indexmap/src/map.rs new file mode 100644 index 0000000000..fccbde16b7 --- /dev/null +++ b/vendor/indexmap/src/map.rs @@ -0,0 +1,2050 @@ +//! `IndexMap` is a hash table where the iteration order of the key-value +//! pairs is independent of the hash values of the keys. + +pub use mutable_keys::MutableKeys; + +use std::hash::Hash; +use std::hash::BuildHasher; +use std::hash::Hasher; +use std::iter::FromIterator; +use std::collections::hash_map::RandomState; +use std::ops::RangeFull; + +use std::cmp::{max, Ordering}; +use std::fmt; +use std::mem::{replace}; +use std::marker::PhantomData; + +use util::{third, ptrdistance, enumerate}; +use equivalent::Equivalent; +use { + Bucket, + HashValue, +}; + +fn hash_elem_using(build: &B, k: &K) -> HashValue { + let mut h = build.build_hasher(); + k.hash(&mut h); + HashValue(h.finish() as usize) +} + +/// A possibly truncated hash value. +/// +#[derive(Debug)] +struct ShortHash(usize, PhantomData); + +impl ShortHash { + /// Pretend this is a full HashValue, which + /// is completely ok w.r.t determining bucket index + /// + /// - Sz = u32: 32-bit hash is enough to select bucket index + /// - Sz = u64: hash is not truncated + fn into_hash(self) -> HashValue { + HashValue(self.0) + } +} + +impl Copy for ShortHash { } +impl Clone for ShortHash { + #[inline] + fn clone(&self) -> Self { *self } +} + +impl PartialEq for ShortHash { + #[inline] + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } +} + +// Compare ShortHash == HashValue by truncating appropriately +// if applicable before the comparison +impl PartialEq for ShortHash where Sz: Size { + #[inline] + fn eq(&self, rhs: &HashValue) -> bool { + if Sz::is_64_bit() { + self.0 == rhs.0 + } else { + lo32(self.0 as u64) == lo32(rhs.0 as u64) + } + } +} +impl From> for HashValue { + fn from(x: ShortHash) -> Self { HashValue(x.0) } +} + +/// `Pos` is stored in the `indices` array and it points to the index of a +/// `Bucket` in self.core.entries. +/// +/// Pos can be interpreted either as a 64-bit index, or as a 32-bit index and +/// a 32-bit hash. +/// +/// Storing the truncated hash next to the index saves loading the hash from the +/// entry, increasing the cache efficiency. +/// +/// Note that the lower 32 bits of the hash is enough to compute desired +/// position and probe distance in a hash map with less than 2**32 buckets. +/// +/// The IndexMap will simply query its **current raw capacity** to see what its +/// current size class is, and dispatch to the 32-bit or 64-bit lookup code as +/// appropriate. Only the growth code needs some extra logic to handle the +/// transition from one class to another +#[derive(Copy)] +struct Pos { + index: u64, +} + +impl Clone for Pos { + #[inline(always)] + fn clone(&self) -> Self { *self } +} + +impl fmt::Debug for Pos { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.pos() { + Some(i) => write!(f, "Pos({} / {:x})", i, self.index), + None => write!(f, "Pos(None)"), + } + } +} + +impl Pos { + #[inline] + fn none() -> Self { Pos { index: !0 } } + + #[inline] + fn is_none(&self) -> bool { self.index == !0 } + + /// Return the index part of the Pos value inside `Some(_)` if the position + /// is not none, otherwise return `None`. + #[inline] + fn pos(&self) -> Option { + if self.index == !0 { None } else { Some(lo32(self.index as u64)) } + } + + /// Set the index part of the Pos value to `i` + #[inline] + fn set_pos(&mut self, i: usize) + where Sz: Size, + { + debug_assert!(!self.is_none()); + if Sz::is_64_bit() { + self.index = i as u64; + } else { + self.index = i as u64 | ((self.index >> 32) << 32) + } + } + + #[inline] + fn with_hash(i: usize, hash: HashValue) -> Self + where Sz: Size + { + if Sz::is_64_bit() { + Pos { + index: i as u64, + } + } else { + Pos { + index: i as u64 | ((hash.0 as u64) << 32) + } + } + } + + /// “Resolve” the Pos into a combination of its index value and + /// a proxy value to the hash (whether it contains the hash or not + /// depends on the size class of the hash map). + #[inline] + fn resolve(&self) -> Option<(usize, ShortHashProxy)> + where Sz: Size + { + if Sz::is_64_bit() { + if !self.is_none() { + Some((self.index as usize, ShortHashProxy::new(0))) + } else { + None + } + } else { + if !self.is_none() { + let (i, hash) = split_lo_hi(self.index); + Some((i as usize, ShortHashProxy::new(hash as usize))) + } else { + None + } + } + } + + /// Like resolve, but the Pos **must** be non-none. Return its index. + #[inline] + fn resolve_existing_index(&self) -> usize + where Sz: Size + { + debug_assert!(!self.is_none(), "datastructure inconsistent: none where valid Pos expected"); + if Sz::is_64_bit() { + self.index as usize + } else { + let (i, _) = split_lo_hi(self.index); + i as usize + } + } + +} + +#[inline] +fn lo32(x: u64) -> usize { (x & 0xFFFF_FFFF) as usize } + +// split into low, hi parts +#[inline] +fn split_lo_hi(x: u64) -> (u32, u32) { (x as u32, (x >> 32) as u32) } + +// Possibly contains the truncated hash value for an entry, depending on +// the size class. +struct ShortHashProxy(usize, PhantomData); + +impl ShortHashProxy + where Sz: Size +{ + fn new(x: usize) -> Self { + ShortHashProxy(x, PhantomData) + } + + /// Get the hash from either `self` or from a lookup into `entries`, + /// depending on `Sz`. + fn get_short_hash(&self, entries: &[Bucket], index: usize) -> ShortHash { + if Sz::is_64_bit() { + ShortHash(entries[index].hash.0, PhantomData) + } else { + ShortHash(self.0, PhantomData) + } + } +} + +/// A hash table where the iteration order of the key-value pairs is independent +/// of the hash values of the keys. +/// +/// The interface is closely compatible with the standard `HashMap`, but also +/// has additional features. +/// +/// # Order +/// +/// The key-value pairs have a consistent order that is determined by +/// the sequence of insertion and removal calls on the map. The order does +/// not depend on the keys or the hash function at all. +/// +/// All iterators traverse the map in *the order*. +/// +/// The insertion order is preserved, with **notable exceptions** like the +/// `.remove()` or `.swap_remove()` methods. Methods such as `.sort_by()` of +/// course result in a new order, depending on the sorting order. +/// +/// # Indices +/// +/// The key-value pairs are indexed in a compact range without holes in the +/// range `0..self.len()`. For example, the method `.get_full` looks up the +/// index for a key, and the method `.get_index` looks up the key-value pair by +/// index. +/// +/// # Examples +/// +/// ``` +/// use indexmap::IndexMap; +/// +/// // count the frequency of each letter in a sentence. +/// let mut letters = IndexMap::new(); +/// for ch in "a short treatise on fungi".chars() { +/// *letters.entry(ch).or_insert(0) += 1; +/// } +/// +/// assert_eq!(letters[&'s'], 2); +/// assert_eq!(letters[&'t'], 3); +/// assert_eq!(letters[&'u'], 1); +/// assert_eq!(letters.get(&'y'), None); +/// ``` +#[derive(Clone)] +pub struct IndexMap { + core: OrderMapCore, + hash_builder: S, +} + +// core of the map that does not depend on S +#[derive(Clone)] +struct OrderMapCore { + pub(crate) mask: usize, + /// indices are the buckets. indices.len() == raw capacity + pub(crate) indices: Box<[Pos]>, + /// entries is a dense vec of entries in their order. entries.len() == len + pub(crate) entries: Vec>, +} + +#[inline(always)] +fn desired_pos(mask: usize, hash: HashValue) -> usize { + hash.0 & mask +} + +/// The number of steps that `current` is forward of the desired position for hash +#[inline(always)] +fn probe_distance(mask: usize, hash: HashValue, current: usize) -> usize { + current.wrapping_sub(desired_pos(mask, hash)) & mask +} + +enum Inserted { + Done, + Swapped { prev_value: V }, + RobinHood { + probe: usize, + old_pos: Pos, + } +} + +impl fmt::Debug for IndexMap + where K: fmt::Debug + Hash + Eq, + V: fmt::Debug, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.debug_map().entries(self.iter()).finish()); + if cfg!(not(feature = "test_debug")) { + return Ok(()); + } + try!(writeln!(f, "")); + for (i, index) in enumerate(&*self.core.indices) { + try!(write!(f, "{}: {:?}", i, index)); + if let Some(pos) = index.pos() { + let hash = self.core.entries[pos].hash; + let key = &self.core.entries[pos].key; + let desire = desired_pos(self.core.mask, hash); + try!(write!(f, ", desired={}, probe_distance={}, key={:?}", + desire, + probe_distance(self.core.mask, hash, i), + key)); + } + try!(writeln!(f, "")); + } + try!(writeln!(f, "cap={}, raw_cap={}, entries.cap={}", + self.capacity(), + self.raw_capacity(), + self.core.entries.capacity())); + Ok(()) + } +} + +#[inline] +fn usable_capacity(cap: usize) -> usize { + cap - cap / 4 +} + +#[inline] +fn to_raw_capacity(n: usize) -> usize { + n + n / 3 +} + +// this could not be captured in an efficient iterator +macro_rules! probe_loop { + ($probe_var: ident < $len: expr, $body: expr) => { + loop { + if $probe_var < $len { + $body + $probe_var += 1; + } else { + $probe_var = 0; + } + } + } +} + +impl IndexMap { + /// Create a new map. (Does not allocate.) + pub fn new() -> Self { + Self::with_capacity(0) + } + + /// Create a new map with capacity for `n` key-value pairs. (Does not + /// allocate if `n` is zero.) + /// + /// Computes in **O(n)** time. + pub fn with_capacity(n: usize) -> Self { + Self::with_capacity_and_hasher(n, <_>::default()) + } +} + +impl IndexMap +{ + /// Create a new map with capacity for `n` key-value pairs. (Does not + /// allocate if `n` is zero.) + /// + /// Computes in **O(n)** time. + pub fn with_capacity_and_hasher(n: usize, hash_builder: S) -> Self + where S: BuildHasher + { + if n == 0 { + IndexMap { + core: OrderMapCore { + mask: 0, + indices: Box::new([]), + entries: Vec::new(), + }, + hash_builder: hash_builder, + } + } else { + let raw = to_raw_capacity(n); + let raw_cap = max(raw.next_power_of_two(), 8); + IndexMap { + core: OrderMapCore { + mask: raw_cap.wrapping_sub(1), + indices: vec![Pos::none(); raw_cap].into_boxed_slice(), + entries: Vec::with_capacity(usable_capacity(raw_cap)), + }, + hash_builder: hash_builder, + } + } + } + + /// Return the number of key-value pairs in the map. + /// + /// Computes in **O(1)** time. + pub fn len(&self) -> usize { self.core.len() } + + /// Returns true if the map contains no elements. + /// + /// Computes in **O(1)** time. + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Create a new map with `hash_builder` + pub fn with_hasher(hash_builder: S) -> Self + where S: BuildHasher + { + Self::with_capacity_and_hasher(0, hash_builder) + } + + /// Return a reference to the map's `BuildHasher`. + pub fn hasher(&self) -> &S + where S: BuildHasher + { + &self.hash_builder + } + + /// Computes in **O(1)** time. + pub fn capacity(&self) -> usize { + self.core.capacity() + } + + #[inline] + fn size_class_is_64bit(&self) -> bool { + self.core.size_class_is_64bit() + } + + #[inline(always)] + fn raw_capacity(&self) -> usize { + self.core.raw_capacity() + } +} + +impl OrderMapCore { + // Return whether we need 32 or 64 bits to specify a bucket or entry index + #[cfg(not(feature = "test_low_transition_point"))] + fn size_class_is_64bit(&self) -> bool { + usize::max_value() > u32::max_value() as usize && + self.raw_capacity() >= u32::max_value() as usize + } + + // for testing + #[cfg(feature = "test_low_transition_point")] + fn size_class_is_64bit(&self) -> bool { + self.raw_capacity() >= 64 + } + + #[inline(always)] + fn raw_capacity(&self) -> usize { + self.indices.len() + } +} + +/// Trait for the "size class". Either u32 or u64 depending on the index +/// size needed to address an entry's indes in self.core.entries. +trait Size { + fn is_64_bit() -> bool; + fn is_same_size() -> bool { + Self::is_64_bit() == T::is_64_bit() + } +} + +impl Size for u32 { + #[inline] + fn is_64_bit() -> bool { false } +} + +impl Size for u64 { + #[inline] + fn is_64_bit() -> bool { true } +} + +/// Call self.method(args) with `::` or `::` depending on `self` +/// size class. +/// +/// The u32 or u64 is *prepended* to the type parameter list! +macro_rules! dispatch_32_vs_64 { + // self.methodname with other explicit type params, + // size is prepended + ($self_:ident . $method:ident::<$($t:ty),*>($($arg:expr),*)) => { + if $self_.size_class_is_64bit() { + $self_.$method::($($arg),*) + } else { + $self_.$method::($($arg),*) + } + }; + // self.methodname with only one type param, the size. + ($self_:ident . $method:ident ($($arg:expr),*)) => { + if $self_.size_class_is_64bit() { + $self_.$method::($($arg),*) + } else { + $self_.$method::($($arg),*) + } + }; + // functionname with size_class_is_64bit as the first argument, only one + // type param, the size. + ($self_:ident => $function:ident ($($arg:expr),*)) => { + if $self_.size_class_is_64bit() { + $function::($($arg),*) + } else { + $function::($($arg),*) + } + }; +} + +/// Entry for an existing key-value pair or a vacant location to +/// insert one. +pub enum Entry<'a, K: 'a, V: 'a> { + /// Existing slot with equivalent key. + Occupied(OccupiedEntry<'a, K, V>), + /// Vacant slot (no equivalent key in the map). + Vacant(VacantEntry<'a, K, V>), +} + +impl<'a, K, V> Entry<'a, K, V> { + /// Computes in **O(1)** time (amortized average). + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(default), + } + } + + /// Computes in **O(1)** time (amortized average). + pub fn or_insert_with(self, call: F) -> &'a mut V + where F: FnOnce() -> V, + { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(call()), + } + } + + pub fn key(&self) -> &K { + match *self { + Entry::Occupied(ref entry) => entry.key(), + Entry::Vacant(ref entry) => entry.key(), + } + } + + /// Return the index where the key-value pair exists or will be inserted. + pub fn index(&self) -> usize { + match *self { + Entry::Occupied(ref entry) => entry.index(), + Entry::Vacant(ref entry) => entry.index(), + } + } + + /// Modifies the entry if it is occupied. + pub fn and_modify(self, f: F) -> Self + where F: FnOnce(&mut V), + { + match self { + Entry::Occupied(mut o) => { + f(o.get_mut()); + Entry::Occupied(o) + } + x => x, + } + } + + /// Inserts a default-constructed value in the entry if it is vacant and returns a mutable + /// reference to it. Otherwise a mutable reference to an already existent value is returned. + /// + /// Computes in **O(1)** time (amortized average). + pub fn or_default(self) -> &'a mut V + where V: Default + { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(V::default()), + } + } +} + +pub struct OccupiedEntry<'a, K: 'a, V: 'a> { + map: &'a mut OrderMapCore, + key: K, + probe: usize, + index: usize, +} + +impl<'a, K, V> OccupiedEntry<'a, K, V> { + pub fn key(&self) -> &K { &self.key } + pub fn get(&self) -> &V { + &self.map.entries[self.index].value + } + pub fn get_mut(&mut self) -> &mut V { + &mut self.map.entries[self.index].value + } + + /// Put the new key in the occupied entry's key slot + pub(crate) fn replace_key(self) -> K { + let old_key = &mut self.map.entries[self.index].key; + replace(old_key, self.key) + } + + /// Return the index of the key-value pair + pub fn index(&self) -> usize { + self.index + } + pub fn into_mut(self) -> &'a mut V { + &mut self.map.entries[self.index].value + } + + /// Sets the value of the entry to `value`, and returns the entry's old value. + pub fn insert(&mut self, value: V) -> V { + replace(self.get_mut(), value) + } + + pub fn remove(self) -> V { + self.remove_entry().1 + } + + /// Remove and return the key, value pair stored in the map for this entry + pub fn remove_entry(self) -> (K, V) { + self.map.remove_found(self.probe, self.index) + } +} + + +pub struct VacantEntry<'a, K: 'a, V: 'a> { + map: &'a mut OrderMapCore, + key: K, + hash: HashValue, + probe: usize, +} + +impl<'a, K, V> VacantEntry<'a, K, V> { + pub fn key(&self) -> &K { &self.key } + pub fn into_key(self) -> K { self.key } + /// Return the index where the key-value pair will be inserted. + pub fn index(&self) -> usize { self.map.len() } + pub fn insert(self, value: V) -> &'a mut V { + if self.map.size_class_is_64bit() { + self.insert_impl::(value) + } else { + self.insert_impl::(value) + } + } + + fn insert_impl(self, value: V) -> &'a mut V + where Sz: Size + { + let index = self.map.entries.len(); + self.map.entries.push(Bucket { hash: self.hash, key: self.key, value: value }); + let old_pos = Pos::with_hash::(index, self.hash); + self.map.insert_phase_2::(self.probe, old_pos); + &mut {self.map}.entries[index].value + } +} + +impl IndexMap + where K: Hash + Eq, + S: BuildHasher, +{ + // FIXME: reduce duplication (compare with insert) + fn entry_phase_1(&mut self, key: K) -> Entry + where Sz: Size + { + let hash = hash_elem_using(&self.hash_builder, &key); + self.core.entry_phase_1::(hash, key) + } + + /// Remove all key-value pairs in the map, while preserving its capacity. + /// + /// Computes in **O(n)** time. + pub fn clear(&mut self) { + self.core.clear(); + } + + /// Reserve capacity for `additional` more key-value pairs. + /// + /// FIXME Not implemented fully yet. + pub fn reserve(&mut self, additional: usize) { + if additional > 0 { + self.reserve_one(); + } + } + + // First phase: Look for the preferred location for key. + // + // We will know if `key` is already in the map, before we need to insert it. + // When we insert they key, it might be that we need to continue displacing + // entries (robin hood hashing), in which case Inserted::RobinHood is returned + fn insert_phase_1(&mut self, key: K, value: V) -> Inserted + where Sz: Size + { + let hash = hash_elem_using(&self.hash_builder, &key); + self.core.insert_phase_1::(hash, key, value) + } + + fn reserve_one(&mut self) { + if self.len() == self.capacity() { + dispatch_32_vs_64!(self.double_capacity()); + } + } + fn double_capacity(&mut self) + where Sz: Size, + { + self.core.double_capacity::(); + } + + /// Insert a key-value pair in the map. + /// + /// If an equivalent key already exists in the map: the key remains and + /// retains in its place in the order, its corresponding value is updated + /// with `value` and the older value is returned inside `Some(_)`. + /// + /// If no equivalent key existed in the map: the new key-value pair is + /// inserted, last in order, and `None` is returned. + /// + /// Computes in **O(1)** time (amortized average). + /// + /// See also [`entry`](#method.entry) if you you want to insert *or* modify + /// or if you need to get the index of the corresponding key-value pair. + pub fn insert(&mut self, key: K, value: V) -> Option { + self.reserve_one(); + if self.size_class_is_64bit() { + match self.insert_phase_1::(key, value) { + Inserted::Swapped { prev_value } => Some(prev_value), + Inserted::Done => None, + Inserted::RobinHood { probe, old_pos } => { + self.core.insert_phase_2::(probe, old_pos); + None + } + } + } else { + match self.insert_phase_1::(key, value) { + Inserted::Swapped { prev_value } => Some(prev_value), + Inserted::Done => None, + Inserted::RobinHood { probe, old_pos } => { + self.core.insert_phase_2::(probe, old_pos); + None + } + } + } + } + + /// Insert a key-value pair in the map, and get their index. + /// + /// If an equivalent key already exists in the map: the key remains and + /// retains in its place in the order, its corresponding value is updated + /// with `value` and the older value is returned inside `(index, Some(_))`. + /// + /// If no equivalent key existed in the map: the new key-value pair is + /// inserted, last in order, and `(index, None)` is returned. + /// + /// Computes in **O(1)** time (amortized average). + /// + /// See also [`entry`](#method.entry) if you you want to insert *or* modify + /// or if you need to get the index of the corresponding key-value pair. + pub fn insert_full(&mut self, key: K, value: V) -> (usize, Option) { + let entry = self.entry(key); + let index = entry.index(); + + match entry { + Entry::Occupied(mut entry) => (index, Some(entry.insert(value))), + Entry::Vacant(entry) => { + entry.insert(value); + (index, None) + } + } + } + + /// Get the given key’s corresponding entry in the map for insertion and/or + /// in-place manipulation. + /// + /// Computes in **O(1)** time (amortized average). + pub fn entry(&mut self, key: K) -> Entry { + self.reserve_one(); + dispatch_32_vs_64!(self.entry_phase_1(key)) + } + + + /// Return an iterator over the key-value pairs of the map, in their order + pub fn iter(&self) -> Iter { + Iter { + iter: self.core.entries.iter() + } + } + + /// Return an iterator over the key-value pairs of the map, in their order + pub fn iter_mut(&mut self) -> IterMut { + IterMut { + iter: self.core.entries.iter_mut() + } + } + + /// Return an iterator over the keys of the map, in their order + pub fn keys(&self) -> Keys { + Keys { + iter: self.core.entries.iter() + } + } + + /// Return an iterator over the values of the map, in their order + pub fn values(&self) -> Values { + Values { + iter: self.core.entries.iter() + } + } + + /// Return an iterator over mutable references to the the values of the map, + /// in their order + pub fn values_mut(&mut self) -> ValuesMut { + ValuesMut { + iter: self.core.entries.iter_mut() + } + } + + /// Return `true` if an equivalent to `key` exists in the map. + /// + /// Computes in **O(1)** time (average). + pub fn contains_key(&self, key: &Q) -> bool + where Q: Hash + Equivalent, + { + self.find(key).is_some() + } + + /// Return a reference to the value stored for `key`, if it is present, + /// else `None`. + /// + /// Computes in **O(1)** time (average). + pub fn get(&self, key: &Q) -> Option<&V> + where Q: Hash + Equivalent, + { + self.get_full(key).map(third) + } + + /// Return item index, key and value + pub fn get_full(&self, key: &Q) -> Option<(usize, &K, &V)> + where Q: Hash + Equivalent, + { + if let Some((_, found)) = self.find(key) { + let entry = &self.core.entries[found]; + Some((found, &entry.key, &entry.value)) + } else { + None + } + } + + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where Q: Hash + Equivalent, + { + self.get_full_mut(key).map(third) + } + + pub fn get_full_mut(&mut self, key: &Q) + -> Option<(usize, &K, &mut V)> + where Q: Hash + Equivalent, + { + self.get_full_mut2_impl(key).map(|(i, k, v)| (i, &*k, v)) + } + + + pub(crate) fn get_full_mut2_impl(&mut self, key: &Q) + -> Option<(usize, &mut K, &mut V)> + where Q: Hash + Equivalent, + { + if let Some((_, found)) = self.find(key) { + let entry = &mut self.core.entries[found]; + Some((found, &mut entry.key, &mut entry.value)) + } else { + None + } + } + + + /// Return probe (indices) and position (entries) + pub(crate) fn find(&self, key: &Q) -> Option<(usize, usize)> + where Q: Hash + Equivalent, + { + if self.len() == 0 { return None; } + let h = hash_elem_using(&self.hash_builder, key); + self.core.find_using(h, move |entry| { Q::equivalent(key, &entry.key) }) + } + + /// NOTE: Same as .swap_remove + /// + /// Computes in **O(1)** time (average). + pub fn remove(&mut self, key: &Q) -> Option + where Q: Hash + Equivalent, + { + self.swap_remove(key) + } + + /// Remove the key-value pair equivalent to `key` and return + /// its value. + /// + /// Like `Vec::swap_remove`, the pair is removed by swapping it with the + /// last element of the map and popping it off. **This perturbs + /// the postion of what used to be the last element!** + /// + /// Return `None` if `key` is not in map. + /// + /// Computes in **O(1)** time (average). + pub fn swap_remove(&mut self, key: &Q) -> Option + where Q: Hash + Equivalent, + { + self.swap_remove_full(key).map(third) + } + + /// Remove the key-value pair equivalent to `key` and return it and + /// the index it had. + /// + /// Like `Vec::swap_remove`, the pair is removed by swapping it with the + /// last element of the map and popping it off. **This perturbs + /// the postion of what used to be the last element!** + /// + /// Return `None` if `key` is not in map. + pub fn swap_remove_full(&mut self, key: &Q) -> Option<(usize, K, V)> + where Q: Hash + Equivalent, + { + let (probe, found) = match self.find(key) { + None => return None, + Some(t) => t, + }; + let (k, v) = self.core.remove_found(probe, found); + Some((found, k, v)) + } + + /// Remove the last key-value pair + /// + /// Computes in **O(1)** time (average). + pub fn pop(&mut self) -> Option<(K, V)> { + self.core.pop_impl() + } + + /// Scan through each key-value pair in the map and keep those where the + /// closure `keep` returns `true`. + /// + /// The elements are visited in order, and remaining elements keep their + /// order. + /// + /// Computes in **O(n)** time (average). + pub fn retain(&mut self, mut keep: F) + where F: FnMut(&K, &mut V) -> bool, + { + self.retain_mut(move |k, v| keep(k, v)); + } + + pub(crate) fn retain_mut(&mut self, keep: F) + where F: FnMut(&mut K, &mut V) -> bool, + { + dispatch_32_vs_64!(self.retain_mut_sz::<_>(keep)); + } + + fn retain_mut_sz(&mut self, keep: F) + where F: FnMut(&mut K, &mut V) -> bool, + Sz: Size, + { + self.core.retain_in_order_impl::(keep); + } + + /// Sort the map’s key-value pairs by the default ordering of the keys. + /// + /// See `sort_by` for details. + pub fn sort_keys(&mut self) + where K: Ord, + { + self.core.sort_by(key_cmp) + } + + /// Sort the map’s key-value pairs in place using the comparison + /// function `compare`. + /// + /// The comparison function receives two key and value pairs to compare (you + /// can sort by keys or values or their combination as needed). + /// + /// Computes in **O(n log n + c)** time and **O(n)** space where *n* is + /// the length of the map and *c* the capacity. The sort is stable. + pub fn sort_by(&mut self, compare: F) + where F: FnMut(&K, &V, &K, &V) -> Ordering, + { + self.core.sort_by(compare) + } + + /// Sort the key-value pairs of the map and return a by value iterator of + /// the key-value pairs with the result. + /// + /// The sort is stable. + pub fn sorted_by(mut self, mut cmp: F) -> IntoIter + where F: FnMut(&K, &V, &K, &V) -> Ordering + { + self.core.entries.sort_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value)); + self.into_iter() + } + + /// Clears the `IndexMap`, returning all key-value pairs as a drain iterator. + /// Keeps the allocated memory for reuse. + pub fn drain(&mut self, range: RangeFull) -> Drain { + self.core.clear_indices(); + + Drain { + iter: self.core.entries.drain(range), + } + } +} + +fn key_cmp(k1: &K, _v1: &V, k2: &K, _v2: &V) -> Ordering + where K: Ord +{ + Ord::cmp(k1, k2) +} + +impl IndexMap { + /// Get a key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index(&self, index: usize) -> Option<(&K, &V)> { + self.core.entries.get(index).map(Bucket::refs) + } + + /// Get a key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index_mut(&mut self, index: usize) -> Option<(&mut K, &mut V)> { + self.core.entries.get_mut(index).map(Bucket::muts) + } + + /// Remove the key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time (average). + pub fn swap_remove_index(&mut self, index: usize) -> Option<(K, V)> { + let (probe, found) = match self.core.entries.get(index) + .map(|e| self.core.find_existing_entry(e)) + { + None => return None, + Some(t) => t, + }; + Some(self.core.remove_found(probe, found)) + } +} + +// Methods that don't use any properties (Hash / Eq) of K. +// +// It's cleaner to separate them out, then the compiler checks that we are not +// using Hash + Eq at all in these methods. +// +// However, we should probably not let this show in the public API or docs. +impl OrderMapCore { + fn len(&self) -> usize { self.entries.len() } + + fn capacity(&self) -> usize { + usable_capacity(self.raw_capacity()) + } + + fn clear(&mut self) { + self.entries.clear(); + self.clear_indices(); + } + + // clear self.indices to the same state as "no elements" + fn clear_indices(&mut self) { + for pos in self.indices.iter_mut() { + *pos = Pos::none(); + } + } + + fn first_allocation(&mut self) { + debug_assert_eq!(self.len(), 0); + let raw_cap = 8usize; + self.mask = raw_cap.wrapping_sub(1); + self.indices = vec![Pos::none(); raw_cap].into_boxed_slice(); + self.entries = Vec::with_capacity(usable_capacity(raw_cap)); + } + + #[inline(never)] + // `Sz` is *current* Size class, before grow + fn double_capacity(&mut self) + where Sz: Size + { + debug_assert!(self.raw_capacity() == 0 || self.len() > 0); + if self.raw_capacity() == 0 { + return self.first_allocation(); + } + + // find first ideally placed element -- start of cluster + let mut first_ideal = 0; + for (i, index) in enumerate(&*self.indices) { + if let Some(pos) = index.pos() { + if 0 == probe_distance(self.mask, self.entries[pos].hash, i) { + first_ideal = i; + break; + } + } + } + + // visit the entries in an order where we can simply reinsert them + // into self.indices without any bucket stealing. + let new_raw_cap = self.indices.len() * 2; + let old_indices = replace(&mut self.indices, vec![Pos::none(); new_raw_cap].into_boxed_slice()); + self.mask = new_raw_cap.wrapping_sub(1); + + // `Sz` is the old size class, and either u32 or u64 is the new + for &pos in &old_indices[first_ideal..] { + dispatch_32_vs_64!(self.reinsert_entry_in_order::(pos)); + } + + for &pos in &old_indices[..first_ideal] { + dispatch_32_vs_64!(self.reinsert_entry_in_order::(pos)); + } + let more = self.capacity() - self.len(); + self.entries.reserve_exact(more); + } + + // write to self.indices + // read from self.entries at `pos` + // + // reinserting rewrites all `Pos` entries anyway. This handles transitioning + // from u32 to u64 size class if needed by using the two type parameters. + fn reinsert_entry_in_order(&mut self, pos: Pos) + where SzNew: Size, + SzOld: Size, + { + if let Some((i, hash_proxy)) = pos.resolve::() { + // only if the size class is conserved can we use the short hash + let entry_hash = if SzOld::is_same_size::() { + hash_proxy.get_short_hash(&self.entries, i).into_hash() + } else { + self.entries[i].hash + }; + // find first empty bucket and insert there + let mut probe = desired_pos(self.mask, entry_hash); + probe_loop!(probe < self.indices.len(), { + if let Some(_) = self.indices[probe].resolve::() { + /* nothing */ + } else { + // empty bucket, insert here + self.indices[probe] = Pos::with_hash::(i, entry_hash); + return; + } + }); + } + } + + fn pop_impl(&mut self) -> Option<(K, V)> { + let (probe, found) = match self.entries.last() + .map(|e| self.find_existing_entry(e)) + { + None => return None, + Some(t) => t, + }; + debug_assert_eq!(found, self.entries.len() - 1); + Some(self.remove_found(probe, found)) + } + + // FIXME: reduce duplication (compare with insert) + fn entry_phase_1(&mut self, hash: HashValue, key: K) -> Entry + where Sz: Size, + K: Eq, + { + let mut probe = desired_pos(self.mask, hash); + let mut dist = 0; + debug_assert!(self.len() < self.raw_capacity()); + probe_loop!(probe < self.indices.len(), { + if let Some((i, hash_proxy)) = self.indices[probe].resolve::() { + let entry_hash = hash_proxy.get_short_hash(&self.entries, i); + // if existing element probed less than us, swap + let their_dist = probe_distance(self.mask, entry_hash.into_hash(), probe); + if their_dist < dist { + // robin hood: steal the spot if it's better for us + return Entry::Vacant(VacantEntry { + map: self, + hash: hash, + key: key, + probe: probe, + }); + } else if entry_hash == hash && self.entries[i].key == key { + return Entry::Occupied(OccupiedEntry { + map: self, + key: key, + probe: probe, + index: i, + }); + } + } else { + // empty bucket, insert here + return Entry::Vacant(VacantEntry { + map: self, + hash: hash, + key: key, + probe: probe, + }); + } + dist += 1; + }); + } + + // First phase: Look for the preferred location for key. + // + // We will know if `key` is already in the map, before we need to insert it. + // When we insert they key, it might be that we need to continue displacing + // entries (robin hood hashing), in which case Inserted::RobinHood is returned + fn insert_phase_1(&mut self, hash: HashValue, key: K, value: V) -> Inserted + where Sz: Size, + K: Eq, + { + let mut probe = desired_pos(self.mask, hash); + let mut dist = 0; + let insert_kind; + debug_assert!(self.len() < self.raw_capacity()); + probe_loop!(probe < self.indices.len(), { + let pos = &mut self.indices[probe]; + if let Some((i, hash_proxy)) = pos.resolve::() { + let entry_hash = hash_proxy.get_short_hash(&self.entries, i); + // if existing element probed less than us, swap + let their_dist = probe_distance(self.mask, entry_hash.into_hash(), probe); + if their_dist < dist { + // robin hood: steal the spot if it's better for us + let index = self.entries.len(); + insert_kind = Inserted::RobinHood { + probe: probe, + old_pos: Pos::with_hash::(index, hash), + }; + break; + } else if entry_hash == hash && self.entries[i].key == key { + return Inserted::Swapped { + prev_value: replace(&mut self.entries[i].value, value), + }; + } + } else { + // empty bucket, insert here + let index = self.entries.len(); + *pos = Pos::with_hash::(index, hash); + insert_kind = Inserted::Done; + break; + } + dist += 1; + }); + self.entries.push(Bucket { hash: hash, key: key, value: value }); + insert_kind + } + + + /// phase 2 is post-insert where we forward-shift `Pos` in the indices. + fn insert_phase_2(&mut self, mut probe: usize, mut old_pos: Pos) + where Sz: Size + { + probe_loop!(probe < self.indices.len(), { + let pos = &mut self.indices[probe]; + if pos.is_none() { + *pos = old_pos; + break; + } else { + old_pos = replace(pos, old_pos); + } + }); + } + + + /// Return probe (indices) and position (entries) + fn find_using(&self, hash: HashValue, key_eq: F) -> Option<(usize, usize)> + where F: Fn(&Bucket) -> bool, + { + dispatch_32_vs_64!(self.find_using_impl::<_>(hash, key_eq)) + } + + fn find_using_impl(&self, hash: HashValue, key_eq: F) -> Option<(usize, usize)> + where F: Fn(&Bucket) -> bool, + Sz: Size, + { + debug_assert!(self.len() > 0); + let mut probe = desired_pos(self.mask, hash); + let mut dist = 0; + probe_loop!(probe < self.indices.len(), { + if let Some((i, hash_proxy)) = self.indices[probe].resolve::() { + let entry_hash = hash_proxy.get_short_hash(&self.entries, i); + if dist > probe_distance(self.mask, entry_hash.into_hash(), probe) { + // give up when probe distance is too long + return None; + } else if entry_hash == hash && key_eq(&self.entries[i]) { + return Some((probe, i)); + } + } else { + return None; + } + dist += 1; + }); + } + + /// Find `entry` which is already placed inside self.entries; + /// return its probe and entry index. + fn find_existing_entry(&self, entry: &Bucket) -> (usize, usize) + { + debug_assert!(self.len() > 0); + + let hash = entry.hash; + let actual_pos = ptrdistance(&self.entries[0], entry); + let probe = dispatch_32_vs_64!(self => + find_existing_entry_at(&self.indices, hash, self.mask, actual_pos)); + (probe, actual_pos) + } + + fn remove_found(&mut self, probe: usize, found: usize) -> (K, V) { + dispatch_32_vs_64!(self.remove_found_impl(probe, found)) + } + + fn remove_found_impl(&mut self, probe: usize, found: usize) -> (K, V) + where Sz: Size + { + // index `probe` and entry `found` is to be removed + // use swap_remove, but then we need to update the index that points + // to the other entry that has to move + self.indices[probe] = Pos::none(); + let entry = self.entries.swap_remove(found); + + // correct index that points to the entry that had to swap places + if let Some(entry) = self.entries.get(found) { + // was not last element + // examine new element in `found` and find it in indices + let mut probe = desired_pos(self.mask, entry.hash); + probe_loop!(probe < self.indices.len(), { + if let Some((i, _)) = self.indices[probe].resolve::() { + if i >= self.entries.len() { + // found it + self.indices[probe] = Pos::with_hash::(found, entry.hash); + break; + } + } + }); + } + + self.backward_shift_after_removal::(probe); + + (entry.key, entry.value) + } + + fn backward_shift_after_removal(&mut self, probe_at_remove: usize) + where Sz: Size + { + // backward shift deletion in self.indices + // after probe, shift all non-ideally placed indices backward + let mut last_probe = probe_at_remove; + let mut probe = probe_at_remove + 1; + probe_loop!(probe < self.indices.len(), { + if let Some((i, hash_proxy)) = self.indices[probe].resolve::() { + let entry_hash = hash_proxy.get_short_hash(&self.entries, i); + if probe_distance(self.mask, entry_hash.into_hash(), probe) > 0 { + self.indices[last_probe] = self.indices[probe]; + self.indices[probe] = Pos::none(); + } else { + break; + } + } else { + break; + } + last_probe = probe; + }); + } + + fn retain_in_order_impl(&mut self, mut keep: F) + where F: FnMut(&mut K, &mut V) -> bool, + Sz: Size, + { + // Like Vec::retain in self.entries; for each removed key-value pair, + // we clear its corresponding spot in self.indices, and run the + // usual backward shift in self.indices. + let len = self.entries.len(); + let mut n_deleted = 0; + for i in 0..len { + let will_keep; + let hash; + { + let ent = &mut self.entries[i]; + hash = ent.hash; + will_keep = keep(&mut ent.key, &mut ent.value); + }; + let probe = find_existing_entry_at::(&self.indices, hash, self.mask, i); + if !will_keep { + n_deleted += 1; + self.indices[probe] = Pos::none(); + self.backward_shift_after_removal::(probe); + } else if n_deleted > 0 { + self.indices[probe].set_pos::(i - n_deleted); + self.entries.swap(i - n_deleted, i); + } + } + self.entries.truncate(len - n_deleted); + } + + fn sort_by(&mut self, mut compare: F) + where F: FnMut(&K, &V, &K, &V) -> Ordering, + { + // Temporarily use the hash field in a bucket to store the old index. + // Save the old hash values in `side_index`. Then we can sort + // `self.entries` in place. + let mut side_index = Vec::from_iter(enumerate(&mut self.entries).map(|(i, elt)| { + replace(&mut elt.hash, HashValue(i)).get() + })); + + self.entries.sort_by(move |ei, ej| compare(&ei.key, &ei.value, &ej.key, &ej.value)); + + // Write back the hash values from side_index and fill `side_index` with + // a mapping from the old to the new index instead. + for (i, ent) in enumerate(&mut self.entries) { + let old_index = ent.hash.get(); + ent.hash = HashValue(replace(&mut side_index[old_index], i)); + } + + // Apply new index to self.indices + dispatch_32_vs_64!(self => apply_new_index(&mut self.indices, &side_index)); + + fn apply_new_index(indices: &mut [Pos], new_index: &[usize]) + where Sz: Size + { + for pos in indices { + if let Some((i, _)) = pos.resolve::() { + pos.set_pos::(new_index[i]); + } + } + } + } +} + +/// Find, in the indices, an entry that already exists at a known position +/// inside self.entries in the IndexMap. +/// +/// This is effectively reverse lookup, from the entries into the hash buckets. +/// +/// Return the probe index (into self.indices) +/// +/// + indices: The self.indices of the map, +/// + hash: The full hash value from the bucket +/// + mask: self.mask. +/// + entry_index: The index of the entry in self.entries +fn find_existing_entry_at(indices: &[Pos], hash: HashValue, + mask: usize, entry_index: usize) -> usize + where Sz: Size, +{ + let mut probe = desired_pos(mask, hash); + probe_loop!(probe < indices.len(), { + // the entry *must* be present; if we hit a Pos::none this was not true + // and there is a debug assertion in resolve_existing_index for that. + let i = indices[probe].resolve_existing_index::(); + if i == entry_index { return probe; } + }); +} + +use std::slice::Iter as SliceIter; +use std::slice::IterMut as SliceIterMut; +use std::vec::IntoIter as VecIntoIter; + +pub struct Keys<'a, K: 'a, V: 'a> { + pub(crate) iter: SliceIter<'a, Bucket>, +} + +impl<'a, K, V> Iterator for Keys<'a, K, V> { + type Item = &'a K; + + iterator_methods!(Bucket::key_ref); +} + +impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { + fn next_back(&mut self) -> Option<&'a K> { + self.iter.next_back().map(Bucket::key_ref) + } +} + +impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { + fn len(&self) -> usize { + self.iter.len() + } +} + +pub struct Values<'a, K: 'a, V: 'a> { + iter: SliceIter<'a, Bucket>, +} + +impl<'a, K, V> Iterator for Values<'a, K, V> { + type Item = &'a V; + + iterator_methods!(Bucket::value_ref); +} + +impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(Bucket::value_ref) + } +} + +impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { + fn len(&self) -> usize { + self.iter.len() + } +} + +pub struct ValuesMut<'a, K: 'a, V: 'a> { + iter: SliceIterMut<'a, Bucket>, +} + +impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { + type Item = &'a mut V; + + iterator_methods!(Bucket::value_mut); +} + +impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(Bucket::value_mut) + } +} + +impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { + fn len(&self) -> usize { + self.iter.len() + } +} + +pub struct Iter<'a, K: 'a, V: 'a> { + iter: SliceIter<'a, Bucket>, +} + +impl<'a, K, V> Iterator for Iter<'a, K, V> { + type Item = (&'a K, &'a V); + + iterator_methods!(Bucket::refs); +} + +impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(Bucket::refs) + } +} + +impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { + fn len(&self) -> usize { + self.iter.len() + } +} + +pub struct IterMut<'a, K: 'a, V: 'a> { + iter: SliceIterMut<'a, Bucket>, +} + +impl<'a, K, V> Iterator for IterMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + iterator_methods!(Bucket::ref_mut); +} + +impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(Bucket::ref_mut) + } +} + +impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { + fn len(&self) -> usize { + self.iter.len() + } +} + +pub struct IntoIter { + pub(crate) iter: VecIntoIter>, +} + +impl Iterator for IntoIter { + type Item = (K, V); + + iterator_methods!(Bucket::key_value); +} + +impl<'a, K, V> DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(Bucket::key_value) + } +} + +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.iter.len() + } +} + +pub struct Drain<'a, K, V> where K: 'a, V: 'a { + pub(crate) iter: ::std::vec::Drain<'a, Bucket> +} + +impl<'a, K, V> Iterator for Drain<'a, K, V> { + type Item = (K, V); + + iterator_methods!(Bucket::key_value); +} + +impl<'a, K, V> DoubleEndedIterator for Drain<'a, K, V> { + double_ended_iterator_methods!(Bucket::key_value); +} + + +impl<'a, K, V, S> IntoIterator for &'a IndexMap + where K: Hash + Eq, + S: BuildHasher, +{ + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, K, V, S> IntoIterator for &'a mut IndexMap + where K: Hash + Eq, + S: BuildHasher, +{ + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +impl IntoIterator for IndexMap + where K: Hash + Eq, + S: BuildHasher, +{ + type Item = (K, V); + type IntoIter = IntoIter; + fn into_iter(self) -> Self::IntoIter { + IntoIter { + iter: self.core.entries.into_iter(), + } + } +} + +use std::ops::{Index, IndexMut}; + +impl<'a, K, V, Q: ?Sized, S> Index<&'a Q> for IndexMap + where Q: Hash + Equivalent, + K: Hash + Eq, + S: BuildHasher, +{ + type Output = V; + + /// ***Panics*** if `key` is not present in the map. + fn index(&self, key: &'a Q) -> &V { + if let Some(v) = self.get(key) { + v + } else { + panic!("IndexMap: key not found") + } + } +} + +/// Mutable indexing allows changing / updating values of key-value +/// pairs that are already present. +/// +/// You can **not** insert new pairs with index syntax, use `.insert()`. +impl<'a, K, V, Q: ?Sized, S> IndexMut<&'a Q> for IndexMap + where Q: Hash + Equivalent, + K: Hash + Eq, + S: BuildHasher, +{ + /// ***Panics*** if `key` is not present in the map. + fn index_mut(&mut self, key: &'a Q) -> &mut V { + if let Some(v) = self.get_mut(key) { + v + } else { + panic!("IndexMap: key not found") + } + } +} + +impl FromIterator<(K, V)> for IndexMap + where K: Hash + Eq, + S: BuildHasher + Default, +{ + /// Create an `IndexMap` from the sequence of key-value pairs in the + /// iterable. + /// + /// `from_iter` uses the same logic as `extend`. See + /// [`extend`](#method.extend) for more details. + fn from_iter>(iterable: I) -> Self { + let iter = iterable.into_iter(); + let (low, _) = iter.size_hint(); + let mut map = Self::with_capacity_and_hasher(low, <_>::default()); + map.extend(iter); + map + } +} + +impl Extend<(K, V)> for IndexMap + where K: Hash + Eq, + S: BuildHasher, +{ + /// Extend the map with all key-value pairs in the iterable. + /// + /// This is equivalent to calling [`insert`](#method.insert) for each of + /// them in order, which means that for keys that already existed + /// in the map, their value is updated but it keeps the existing order. + /// + /// New keys are inserted inserted in the order in the sequence. If + /// equivalents of a key occur more than once, the last corresponding value + /// prevails. + fn extend>(&mut self, iterable: I) { + for (k, v) in iterable { self.insert(k, v); } + } +} + +impl<'a, K, V, S> Extend<(&'a K, &'a V)> for IndexMap + where K: Hash + Eq + Copy, + V: Copy, + S: BuildHasher, +{ + /// Extend the map with all key-value pairs in the iterable. + /// + /// See the first extend method for more details. + fn extend>(&mut self, iterable: I) { + self.extend(iterable.into_iter().map(|(&key, &value)| (key, value))); + } +} + +impl Default for IndexMap + where S: BuildHasher + Default, +{ + /// Return an empty `IndexMap` + fn default() -> Self { + Self::with_capacity_and_hasher(0, S::default()) + } +} + +impl PartialEq> for IndexMap + where K: Hash + Eq, + V1: PartialEq, + S1: BuildHasher, + S2: BuildHasher +{ + fn eq(&self, other: &IndexMap) -> bool { + if self.len() != other.len() { + return false; + } + + self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) + } +} + +impl Eq for IndexMap + where K: Eq + Hash, + V: Eq, + S: BuildHasher +{ +} + +#[cfg(test)] +mod tests { + use super::*; + use util::enumerate; + + #[test] + fn it_works() { + let mut map = IndexMap::new(); + assert_eq!(map.is_empty(), true); + map.insert(1, ()); + map.insert(1, ()); + assert_eq!(map.len(), 1); + assert!(map.get(&1).is_some()); + assert_eq!(map.is_empty(), false); + } + + #[test] + fn new() { + let map = IndexMap::::new(); + println!("{:?}", map); + assert_eq!(map.capacity(), 0); + assert_eq!(map.len(), 0); + assert_eq!(map.is_empty(), true); + } + + #[test] + fn insert() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5]; + let not_present = [1, 3, 6, 9, 10]; + let mut map = IndexMap::with_capacity(insert.len()); + + for (i, &elt) in enumerate(&insert) { + assert_eq!(map.len(), i); + map.insert(elt, elt); + assert_eq!(map.len(), i + 1); + assert_eq!(map.get(&elt), Some(&elt)); + assert_eq!(map[&elt], elt); + } + println!("{:?}", map); + + for &elt in ¬_present { + assert!(map.get(&elt).is_none()); + } + } + + #[test] + fn insert_full() { + let insert = vec![9, 2, 7, 1, 4, 6, 13]; + let present = vec![1, 6, 2]; + let mut map = IndexMap::with_capacity(insert.len()); + + for (i, &elt) in enumerate(&insert) { + assert_eq!(map.len(), i); + let (index, existing) = map.insert_full(elt, elt); + assert_eq!(existing, None); + assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0)); + assert_eq!(map.len(), i + 1); + } + + let len = map.len(); + for &elt in &present { + let (index, existing) = map.insert_full(elt, elt); + assert_eq!(existing, Some(elt)); + assert_eq!(Some(index), map.get_full(&elt).map(|x| x.0)); + assert_eq!(map.len(), len); + } + } + + #[test] + fn insert_2() { + let mut map = IndexMap::with_capacity(16); + + let mut keys = vec![]; + keys.extend(0..16); + keys.extend(128..267); + + for &i in &keys { + let old_map = map.clone(); + map.insert(i, ()); + for key in old_map.keys() { + if !map.get(key).is_some() { + println!("old_map: {:?}", old_map); + println!("map: {:?}", map); + panic!("did not find {} in map", key); + } + } + } + + for &i in &keys { + assert!(map.get(&i).is_some(), "did not find {}", i); + } + } + + #[test] + fn insert_order() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut map = IndexMap::new(); + + for &elt in &insert { + map.insert(elt, ()); + } + + assert_eq!(map.keys().count(), map.len()); + assert_eq!(map.keys().count(), insert.len()); + for (a, b) in insert.iter().zip(map.keys()) { + assert_eq!(a, b); + } + for (i, k) in (0..insert.len()).zip(map.keys()) { + assert_eq!(map.get_index(i).unwrap().0, k); + } + } + + #[test] + fn grow() { + let insert = [0, 4, 2, 12, 8, 7, 11]; + let not_present = [1, 3, 6, 9, 10]; + let mut map = IndexMap::with_capacity(insert.len()); + + + for (i, &elt) in enumerate(&insert) { + assert_eq!(map.len(), i); + map.insert(elt, elt); + assert_eq!(map.len(), i + 1); + assert_eq!(map.get(&elt), Some(&elt)); + assert_eq!(map[&elt], elt); + } + + println!("{:?}", map); + for &elt in &insert { + map.insert(elt * 10, elt); + } + for &elt in &insert { + map.insert(elt * 100, elt); + } + for (i, &elt) in insert.iter().cycle().enumerate().take(100) { + map.insert(elt * 100 + i as i32, elt); + } + println!("{:?}", map); + for &elt in ¬_present { + assert!(map.get(&elt).is_none()); + } + } + + #[test] + fn remove() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut map = IndexMap::new(); + + for &elt in &insert { + map.insert(elt, elt); + } + + assert_eq!(map.keys().count(), map.len()); + assert_eq!(map.keys().count(), insert.len()); + for (a, b) in insert.iter().zip(map.keys()) { + assert_eq!(a, b); + } + + let remove_fail = [99, 77]; + let remove = [4, 12, 8, 7]; + + for &key in &remove_fail { + assert!(map.swap_remove_full(&key).is_none()); + } + println!("{:?}", map); + for &key in &remove { + //println!("{:?}", map); + let index = map.get_full(&key).unwrap().0; + assert_eq!(map.swap_remove_full(&key), Some((index, key, key))); + } + println!("{:?}", map); + + for key in &insert { + assert_eq!(map.get(key).is_some(), !remove.contains(key)); + } + assert_eq!(map.len(), insert.len() - remove.len()); + assert_eq!(map.keys().count(), insert.len() - remove.len()); + } + + #[test] + fn remove_to_empty() { + let mut map = indexmap! { 0 => 0, 4 => 4, 5 => 5 }; + map.swap_remove(&5).unwrap(); + map.swap_remove(&4).unwrap(); + map.swap_remove(&0).unwrap(); + assert!(map.is_empty()); + } + + #[test] + fn swap_remove_index() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut map = IndexMap::new(); + + for &elt in &insert { + map.insert(elt, elt * 2); + } + + let mut vector = insert.to_vec(); + let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1]; + + // check that the same swap remove sequence on vec and map + // have the same result. + for &rm in remove_sequence { + let out_vec = vector.swap_remove(rm); + let (out_map, _) = map.swap_remove_index(rm).unwrap(); + assert_eq!(out_vec, out_map); + } + assert_eq!(vector.len(), map.len()); + for (a, b) in vector.iter().zip(map.keys()) { + assert_eq!(a, b); + } + } + + #[test] + fn partial_eq_and_eq() { + let mut map_a = IndexMap::new(); + map_a.insert(1, "1"); + map_a.insert(2, "2"); + let mut map_b = map_a.clone(); + assert_eq!(map_a, map_b); + map_b.remove(&1); + assert_ne!(map_a, map_b); + + let map_c: IndexMap<_, String> = map_b.into_iter().map(|(k, v)| (k, v.to_owned())).collect(); + assert_ne!(map_a, map_c); + assert_ne!(map_c, map_a); + } + + #[test] + fn extend() { + let mut map = IndexMap::new(); + map.extend(vec![(&1, &2), (&3, &4)]); + map.extend(vec![(5, 6)]); + assert_eq!(map.into_iter().collect::>(), vec![(1, 2), (3, 4), (5, 6)]); + } + + #[test] + fn entry() { + let mut map = IndexMap::new(); + + map.insert(1, "1"); + map.insert(2, "2"); + { + let e = map.entry(3); + assert_eq!(e.index(), 2); + let e = e.or_insert("3"); + assert_eq!(e, &"3"); + } + + let e = map.entry(2); + assert_eq!(e.index(), 1); + assert_eq!(e.key(), &2); + match e { + Entry::Occupied(ref e) => assert_eq!(e.get(), &"2"), + Entry::Vacant(_) => panic!() + } + assert_eq!(e.or_insert("4"), &"2"); + } + + #[test] + fn entry_and_modify() { + let mut map = IndexMap::new(); + + map.insert(1, "1"); + map.entry(1).and_modify(|x| *x = "2"); + assert_eq!(Some(&"2"), map.get(&1)); + + map.entry(2).and_modify(|x| *x = "doesn't exist"); + assert_eq!(None, map.get(&2)); + } + + #[test] + fn entry_or_default() { + let mut map = IndexMap::new(); + + #[derive(Debug, PartialEq)] + enum TestEnum { + DefaultValue, + NonDefaultValue, + } + + impl Default for TestEnum { + fn default() -> Self { + TestEnum::DefaultValue + } + } + + map.insert(1, TestEnum::NonDefaultValue); + assert_eq!(&mut TestEnum::NonDefaultValue, map.entry(1).or_default()); + + assert_eq!(&mut TestEnum::DefaultValue, map.entry(2).or_default()); + } +} diff --git a/vendor/indexmap/src/mutable_keys.rs b/vendor/indexmap/src/mutable_keys.rs new file mode 100644 index 0000000000..9291f96f28 --- /dev/null +++ b/vendor/indexmap/src/mutable_keys.rs @@ -0,0 +1,71 @@ + +use std::hash::Hash; +use std::hash::BuildHasher; + +use super::{IndexMap, Equivalent}; + +pub struct PrivateMarker { } + +/// Opt-in mutable access to keys. +/// +/// These methods expose `&mut K`, mutable references to the key as it is stored +/// in the map. +/// You are allowed to modify the keys in the hashmap **if the modifcation +/// does not change the key’s hash and equality**. +/// +/// If keys are modified erronously, you can no longer look them up. +/// This is sound (memory safe) but a logical error hazard (just like +/// implementing PartialEq, Eq, or Hash incorrectly would be). +/// +/// `use` this trait to enable its methods for `IndexMap`. +pub trait MutableKeys { + type Key; + type Value; + + /// Return item index, mutable reference to key and value + fn get_full_mut2(&mut self, key: &Q) + -> Option<(usize, &mut Self::Key, &mut Self::Value)> + where Q: Hash + Equivalent; + + /// Scan through each key-value pair in the map and keep those where the + /// closure `keep` returns `true`. + /// + /// The elements are visited in order, and remaining elements keep their + /// order. + /// + /// Computes in **O(n)** time (average). + fn retain2(&mut self, keep: F) + where F: FnMut(&mut Self::Key, &mut Self::Value) -> bool; + + /// This method is not useful in itself – it is there to “seal” the trait + /// for external implementation, so that we can add methods without + /// causing breaking changes. + fn __private_marker(&self) -> PrivateMarker; +} + +/// Opt-in mutable access to keys. +/// +/// See [`MutableKeys`](trait.MutableKeys.html) for more information. +impl MutableKeys for IndexMap + where K: Eq + Hash, + S: BuildHasher, +{ + type Key = K; + type Value = V; + fn get_full_mut2(&mut self, key: &Q) + -> Option<(usize, &mut K, &mut V)> + where Q: Hash + Equivalent, + { + self.get_full_mut2_impl(key) + } + + fn retain2(&mut self, keep: F) + where F: FnMut(&mut K, &mut V) -> bool, + { + self.retain_mut(keep) + } + + fn __private_marker(&self) -> PrivateMarker { + PrivateMarker { } + } +} diff --git a/vendor/indexmap/src/serde.rs b/vendor/indexmap/src/serde.rs new file mode 100644 index 0000000000..bd082a7c31 --- /dev/null +++ b/vendor/indexmap/src/serde.rs @@ -0,0 +1,123 @@ + +extern crate serde; + +use self::serde::ser::{Serialize, Serializer, SerializeMap, SerializeSeq}; +use self::serde::de::{Deserialize, Deserializer, MapAccess, SeqAccess, Visitor}; + +use std::fmt::{self, Formatter}; +use std::hash::{BuildHasher, Hash}; +use std::marker::PhantomData; + +use IndexMap; + +/// Requires crate feature `"serde-1"` +impl Serialize for IndexMap + where K: Serialize + Hash + Eq, + V: Serialize, + S: BuildHasher +{ + fn serialize(&self, serializer: T) -> Result + where T: Serializer + { + let mut map_serializer = try!(serializer.serialize_map(Some(self.len()))); + for (key, value) in self { + try!(map_serializer.serialize_entry(key, value)); + } + map_serializer.end() + } +} + +struct OrderMapVisitor(PhantomData<(K, V, S)>); + +impl<'de, K, V, S> Visitor<'de> for OrderMapVisitor + where K: Deserialize<'de> + Eq + Hash, + V: Deserialize<'de>, + S: Default + BuildHasher +{ + type Value = IndexMap; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + write!(formatter, "a map") + } + + fn visit_map(self, mut map: A) -> Result + where A: MapAccess<'de> + { + let mut values = IndexMap::with_capacity_and_hasher(map.size_hint().unwrap_or(0), S::default()); + + while let Some((key, value)) = try!(map.next_entry()) { + values.insert(key, value); + } + + Ok(values) + } +} + +/// Requires crate feature `"serde-1"` +impl<'de, K, V, S> Deserialize<'de> for IndexMap + where K: Deserialize<'de> + Eq + Hash, + V: Deserialize<'de>, + S: Default + BuildHasher +{ + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + deserializer.deserialize_map(OrderMapVisitor(PhantomData)) + } +} + + +use IndexSet; + +/// Requires crate feature `"serde-1"` +impl Serialize for IndexSet + where T: Serialize + Hash + Eq, + S: BuildHasher +{ + fn serialize(&self, serializer: Se) -> Result + where Se: Serializer + { + let mut set_serializer = try!(serializer.serialize_seq(Some(self.len()))); + for value in self { + try!(set_serializer.serialize_element(value)); + } + set_serializer.end() + } +} + +struct OrderSetVisitor(PhantomData<(T, S)>); + +impl<'de, T, S> Visitor<'de> for OrderSetVisitor + where T: Deserialize<'de> + Eq + Hash, + S: Default + BuildHasher +{ + type Value = IndexSet; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + write!(formatter, "a set") + } + + fn visit_seq(self, mut seq: A) -> Result + where A: SeqAccess<'de> + { + let mut values = IndexSet::with_capacity_and_hasher(seq.size_hint().unwrap_or(0), S::default()); + + while let Some(value) = try!(seq.next_element()) { + values.insert(value); + } + + Ok(values) + } +} + +/// Requires crate feature `"serde-1"` +impl<'de, T, S> Deserialize<'de> for IndexSet + where T: Deserialize<'de> + Eq + Hash, + S: Default + BuildHasher +{ + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + deserializer.deserialize_seq(OrderSetVisitor(PhantomData)) + } +} diff --git a/vendor/indexmap/src/set.rs b/vendor/indexmap/src/set.rs new file mode 100644 index 0000000000..c1ba3b6d3b --- /dev/null +++ b/vendor/indexmap/src/set.rs @@ -0,0 +1,1180 @@ +//! A hash set implemented using `IndexMap` + +use std::cmp::Ordering; +use std::collections::hash_map::RandomState; +use std::fmt; +use std::iter::{FromIterator, Chain}; +use std::hash::{Hash, BuildHasher}; +use std::ops::RangeFull; +use std::ops::{BitAnd, BitOr, BitXor, Sub}; +use std::slice; +use std::vec; + +use super::{IndexMap, Equivalent}; + +type Bucket = super::Bucket; + +/// A hash set where the iteration order of the values is independent of their +/// hash values. +/// +/// The interface is closely compatible with the standard `HashSet`, but also +/// has additional features. +/// +/// # Order +/// +/// The values have a consistent order that is determined by the sequence of +/// insertion and removal calls on the set. The order does not depend on the +/// values or the hash function at all. Note that insertion order and value +/// are not affected if a re-insertion is attempted once an element is +/// already present. +/// +/// All iterators traverse the set *in order*. Set operation iterators like +/// `union` produce a concatenated order, as do their matching "bitwise" +/// operators. See their documentation for specifics. +/// +/// The insertion order is preserved, with **notable exceptions** like the +/// `.remove()` or `.swap_remove()` methods. Methods such as `.sort_by()` of +/// course result in a new order, depending on the sorting order. +/// +/// # Indices +/// +/// The values are indexed in a compact range without holes in the range +/// `0..self.len()`. For example, the method `.get_full` looks up the index for +/// a value, and the method `.get_index` looks up the value by index. +/// +/// # Examples +/// +/// ``` +/// use indexmap::IndexSet; +/// +/// // Collects which letters appear in a sentence. +/// let letters: IndexSet<_> = "a short treatise on fungi".chars().collect(); +/// +/// assert!(letters.contains(&'s')); +/// assert!(letters.contains(&'t')); +/// assert!(letters.contains(&'u')); +/// assert!(!letters.contains(&'y')); +/// ``` +#[derive(Clone)] +pub struct IndexSet { + map: IndexMap, +} + +impl fmt::Debug for IndexSet + where T: fmt::Debug + Hash + Eq, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if cfg!(not(feature = "test_debug")) { + f.debug_set().entries(self.iter()).finish() + } else { + // Let the inner `IndexMap` print all of its details + f.debug_struct("IndexSet").field("map", &self.map).finish() + } + } +} + +impl IndexSet { + /// Create a new set. (Does not allocate.) + pub fn new() -> Self { + IndexSet { map: IndexMap::new() } + } + + /// Create a new set with capacity for `n` elements. + /// (Does not allocate if `n` is zero.) + /// + /// Computes in **O(n)** time. + pub fn with_capacity(n: usize) -> Self { + IndexSet { map: IndexMap::with_capacity(n) } + } +} + +impl IndexSet { + /// Create a new set with capacity for `n` elements. + /// (Does not allocate if `n` is zero.) + /// + /// Computes in **O(n)** time. + pub fn with_capacity_and_hasher(n: usize, hash_builder: S) -> Self + where S: BuildHasher + { + IndexSet { map: IndexMap::with_capacity_and_hasher(n, hash_builder) } + } + + /// Return the number of elements in the set. + /// + /// Computes in **O(1)** time. + pub fn len(&self) -> usize { + self.map.len() + } + + /// Returns true if the set contains no elements. + /// + /// Computes in **O(1)** time. + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + /// Create a new set with `hash_builder` + pub fn with_hasher(hash_builder: S) -> Self + where S: BuildHasher + { + IndexSet { map: IndexMap::with_hasher(hash_builder) } + } + + /// Return a reference to the set's `BuildHasher`. + pub fn hasher(&self) -> &S + where S: BuildHasher + { + self.map.hasher() + } + + /// Computes in **O(1)** time. + pub fn capacity(&self) -> usize { + self.map.capacity() + } +} + +impl IndexSet + where T: Hash + Eq, + S: BuildHasher, +{ + /// Remove all elements in the set, while preserving its capacity. + /// + /// Computes in **O(n)** time. + pub fn clear(&mut self) { + self.map.clear(); + } + + /// FIXME Not implemented fully yet + pub fn reserve(&mut self, additional: usize) { + self.map.reserve(additional); + } + + /// Insert the value into the set. + /// + /// If an equivalent item already exists in the set, it returns + /// `false` leaving the original value in the set and without + /// altering its insertion order. Otherwise, it inserts the new + /// item and returns `true`. + /// + /// Computes in **O(1)** time (amortized average). + pub fn insert(&mut self, value: T) -> bool { + self.map.insert(value, ()).is_none() + } + + /// Insert the value into the set, and get its index. + /// + /// If an equivalent item already exists in the set, it returns + /// the index of the existing item and `false`, leaving the + /// original value in the set and without altering its insertion + /// order. Otherwise, it inserts the new item and returns the index + /// of the inserted item and `true`. + /// + /// Computes in **O(1)** time (amortized average). + pub fn insert_full(&mut self, value: T) -> (usize, bool) { + use super::map::Entry::*; + + match self.map.entry(value) { + Occupied(e) => (e.index(), false), + Vacant(e) => { + let index = e.index(); + e.insert(()); + (index, true) + } + } + } + + /// Return an iterator over the values of the set, in their order + pub fn iter(&self) -> Iter { + Iter { + iter: self.map.keys().iter + } + } + + /// Return an iterator over the values that are in `self` but not `other`. + /// + /// Values are produced in the same order that they appear in `self`. + pub fn difference<'a, S2>(&'a self, other: &'a IndexSet) -> Difference<'a, T, S2> + where S2: BuildHasher + { + Difference { + iter: self.iter(), + other: other, + } + } + + /// Return an iterator over the values that are in `self` or `other`, + /// but not in both. + /// + /// Values from `self` are produced in their original order, followed by + /// values from `other` in their original order. + pub fn symmetric_difference<'a, S2>(&'a self, other: &'a IndexSet) + -> SymmetricDifference<'a, T, S, S2> + where S2: BuildHasher + { + SymmetricDifference { + iter: self.difference(other).chain(other.difference(self)), + } + } + + /// Return an iterator over the values that are in both `self` and `other`. + /// + /// Values are produced in the same order that they appear in `self`. + pub fn intersection<'a, S2>(&'a self, other: &'a IndexSet) -> Intersection<'a, T, S2> + where S2: BuildHasher + { + Intersection { + iter: self.iter(), + other: other, + } + } + + /// Return an iterator over all values that are in `self` or `other`. + /// + /// Values from `self` are produced in their original order, followed by + /// values that are unique to `other` in their original order. + pub fn union<'a, S2>(&'a self, other: &'a IndexSet) -> Union<'a, T, S> + where S2: BuildHasher + { + Union { + iter: self.iter().chain(other.difference(self)), + } + } + + /// Return `true` if an equivalent to `value` exists in the set. + /// + /// Computes in **O(1)** time (average). + pub fn contains(&self, value: &Q) -> bool + where Q: Hash + Equivalent, + { + self.map.contains_key(value) + } + + /// Return a reference to the value stored in the set, if it is present, + /// else `None`. + /// + /// Computes in **O(1)** time (average). + pub fn get(&self, value: &Q) -> Option<&T> + where Q: Hash + Equivalent, + { + self.map.get_full(value).map(|(_, x, &())| x) + } + + /// Return item index and value + pub fn get_full(&self, value: &Q) -> Option<(usize, &T)> + where Q: Hash + Equivalent, + { + self.map.get_full(value).map(|(i, x, &())| (i, x)) + } + + /// Adds a value to the set, replacing the existing value, if any, that is + /// equal to the given one. Returns the replaced value. + /// + /// Computes in **O(1)** time (average). + pub fn replace(&mut self, value: T) -> Option + { + use super::map::Entry::*; + + match self.map.entry(value) { + Vacant(e) => { e.insert(()); None }, + Occupied(e) => Some(e.replace_key()), + } + } + + /// FIXME Same as .swap_remove + /// + /// Computes in **O(1)** time (average). + pub fn remove(&mut self, value: &Q) -> bool + where Q: Hash + Equivalent, + { + self.swap_remove(value) + } + + /// Remove the value from the set, and return `true` if it was present. + /// + /// Like `Vec::swap_remove`, the value is removed by swapping it with the + /// last element of the set and popping it off. **This perturbs + /// the postion of what used to be the last element!** + /// + /// Return `false` if `value` was not in the set. + /// + /// Computes in **O(1)** time (average). + pub fn swap_remove(&mut self, value: &Q) -> bool + where Q: Hash + Equivalent, + { + self.map.swap_remove(value).is_some() + } + + /// FIXME Same as .swap_take + /// + /// Computes in **O(1)** time (average). + pub fn take(&mut self, value: &Q) -> Option + where Q: Hash + Equivalent, + { + self.swap_take(value) + } + + /// Removes and returns the value in the set, if any, that is equal to the + /// given one. + /// + /// Like `Vec::swap_remove`, the value is removed by swapping it with the + /// last element of the set and popping it off. **This perturbs + /// the postion of what used to be the last element!** + /// + /// Return `None` if `value` was not in the set. + /// + /// Computes in **O(1)** time (average). + pub fn swap_take(&mut self, value: &Q) -> Option + where Q: Hash + Equivalent, + { + self.map.swap_remove_full(value).map(|(_, x, ())| x) + } + + /// Remove the value from the set return it and the index it had. + /// + /// Like `Vec::swap_remove`, the value is removed by swapping it with the + /// last element of the set and popping it off. **This perturbs + /// the postion of what used to be the last element!** + /// + /// Return `None` if `value` was not in the set. + pub fn swap_remove_full(&mut self, value: &Q) -> Option<(usize, T)> + where Q: Hash + Equivalent, + { + self.map.swap_remove_full(value).map(|(i, x, ())| (i, x)) + } + + /// Remove the last value + /// + /// Computes in **O(1)** time (average). + pub fn pop(&mut self) -> Option { + self.map.pop().map(|(x, ())| x) + } + + /// Scan through each value in the set and keep those where the + /// closure `keep` returns `true`. + /// + /// The elements are visited in order, and remaining elements keep their + /// order. + /// + /// Computes in **O(n)** time (average). + pub fn retain(&mut self, mut keep: F) + where F: FnMut(&T) -> bool, + { + self.map.retain(move |x, &mut ()| keep(x)) + } + + /// Sort the set’s values by their default ordering. + /// + /// See `sort_by` for details. + pub fn sort(&mut self) + where T: Ord, + { + self.map.sort_keys() + } + + /// Sort the set’s values in place using the comparison function `compare`. + /// + /// Computes in **O(n log n)** time and **O(n)** space. The sort is stable. + pub fn sort_by(&mut self, mut compare: F) + where F: FnMut(&T, &T) -> Ordering, + { + self.map.sort_by(move |a, _, b, _| compare(a, b)); + } + + /// Sort the values of the set and return a by value iterator of + /// the values with the result. + /// + /// The sort is stable. + pub fn sorted_by(self, mut cmp: F) -> IntoIter + where F: FnMut(&T, &T) -> Ordering + { + IntoIter { + iter: self.map.sorted_by(move |a, &(), b, &()| cmp(a, b)).iter, + } + } + + /// Clears the `IndexSet`, returning all values as a drain iterator. + /// Keeps the allocated memory for reuse. + pub fn drain(&mut self, range: RangeFull) -> Drain { + Drain { + iter: self.map.drain(range).iter, + } + } +} + +impl IndexSet { + /// Get a value by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index(&self, index: usize) -> Option<&T> { + self.map.get_index(index).map(|(x, &())| x) + } + + /// Remove the key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time (average). + pub fn swap_remove_index(&mut self, index: usize) -> Option { + self.map.swap_remove_index(index).map(|(x, ())| x) + } +} + + +pub struct IntoIter { + iter: vec::IntoIter>, +} + +impl Iterator for IntoIter { + type Item = T; + + iterator_methods!(Bucket::key); +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(Bucket::key) + } +} + +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.iter.len() + } +} + + +pub struct Iter<'a, T: 'a> { + iter: slice::Iter<'a, Bucket>, +} + +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + iterator_methods!(Bucket::key_ref); +} + +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(Bucket::key_ref) + } +} + +impl<'a, T> ExactSizeIterator for Iter<'a, T> { + fn len(&self) -> usize { + self.iter.len() + } +} + +pub struct Drain<'a, T: 'a> { + iter: vec::Drain<'a, Bucket>, +} + +impl<'a, T> Iterator for Drain<'a, T> { + type Item = T; + + iterator_methods!(Bucket::key); +} + +impl<'a, T> DoubleEndedIterator for Drain<'a, T> { + double_ended_iterator_methods!(Bucket::key); +} + +impl<'a, T, S> IntoIterator for &'a IndexSet + where T: Hash + Eq, + S: BuildHasher, +{ + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl IntoIterator for IndexSet + where T: Hash + Eq, + S: BuildHasher, +{ + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter { + iter: self.map.into_iter().iter, + } + } +} + +impl FromIterator for IndexSet + where T: Hash + Eq, + S: BuildHasher + Default, +{ + fn from_iter>(iterable: I) -> Self { + let iter = iterable.into_iter().map(|x| (x, ())); + IndexSet { map: IndexMap::from_iter(iter) } + } +} + +impl Extend for IndexSet + where T: Hash + Eq, + S: BuildHasher, +{ + fn extend>(&mut self, iterable: I) { + let iter = iterable.into_iter().map(|x| (x, ())); + self.map.extend(iter); + } +} + +impl<'a, T, S> Extend<&'a T> for IndexSet + where T: Hash + Eq + Copy, + S: BuildHasher, +{ + fn extend>(&mut self, iterable: I) { + let iter = iterable.into_iter().map(|&x| x); + self.extend(iter); + } +} + + +impl Default for IndexSet + where S: BuildHasher + Default, +{ + /// Return an empty `IndexSet` + fn default() -> Self { + IndexSet { map: IndexMap::default() } + } +} + +impl PartialEq> for IndexSet + where T: Hash + Eq, + S1: BuildHasher, + S2: BuildHasher +{ + fn eq(&self, other: &IndexSet) -> bool { + self.len() == other.len() && self.is_subset(other) + } +} + +impl Eq for IndexSet + where T: Eq + Hash, + S: BuildHasher +{ +} + +impl IndexSet + where T: Eq + Hash, + S: BuildHasher +{ + /// Returns `true` if `self` has no elements in common with `other`. + pub fn is_disjoint(&self, other: &IndexSet) -> bool + where S2: BuildHasher + { + if self.len() <= other.len() { + self.iter().all(move |value| !other.contains(value)) + } else { + other.iter().all(move |value| !self.contains(value)) + } + } + + /// Returns `true` if all elements of `self` are contained in `other`. + pub fn is_subset(&self, other: &IndexSet) -> bool + where S2: BuildHasher + { + self.len() <= other.len() && self.iter().all(move |value| other.contains(value)) + } + + /// Returns `true` if all elements of `other` are contained in `self`. + pub fn is_superset(&self, other: &IndexSet) -> bool + where S2: BuildHasher + { + other.is_subset(self) + } +} + + +pub struct Difference<'a, T: 'a, S: 'a> { + iter: Iter<'a, T>, + other: &'a IndexSet, +} + +impl<'a, T, S> Iterator for Difference<'a, T, S> + where T: Eq + Hash, + S: BuildHasher +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + while let Some(item) = self.iter.next() { + if !self.other.contains(item) { + return Some(item); + } + } + None + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } +} + +impl<'a, T, S> DoubleEndedIterator for Difference<'a, T, S> + where T: Eq + Hash, + S: BuildHasher +{ + fn next_back(&mut self) -> Option { + while let Some(item) = self.iter.next_back() { + if !self.other.contains(item) { + return Some(item); + } + } + None + } +} + + +pub struct Intersection<'a, T: 'a, S: 'a> { + iter: Iter<'a, T>, + other: &'a IndexSet, +} + +impl<'a, T, S> Iterator for Intersection<'a, T, S> + where T: Eq + Hash, + S: BuildHasher +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + while let Some(item) = self.iter.next() { + if self.other.contains(item) { + return Some(item); + } + } + None + } + + fn size_hint(&self) -> (usize, Option) { + (0, self.iter.size_hint().1) + } +} + +impl<'a, T, S> DoubleEndedIterator for Intersection<'a, T, S> + where T: Eq + Hash, + S: BuildHasher +{ + fn next_back(&mut self) -> Option { + while let Some(item) = self.iter.next_back() { + if self.other.contains(item) { + return Some(item); + } + } + None + } +} + + +pub struct SymmetricDifference<'a, T: 'a, S1: 'a, S2: 'a> { + iter: Chain, Difference<'a, T, S1>>, +} + +impl<'a, T, S1, S2> Iterator for SymmetricDifference<'a, T, S1, S2> + where T: Eq + Hash, + S1: BuildHasher, + S2: BuildHasher, +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn fold(self, init: B, f: F) -> B + where F: FnMut(B, Self::Item) -> B + { + self.iter.fold(init, f) + } +} + +impl<'a, T, S1, S2> DoubleEndedIterator for SymmetricDifference<'a, T, S1, S2> + where T: Eq + Hash, + S1: BuildHasher, + S2: BuildHasher, +{ + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + + +pub struct Union<'a, T: 'a, S: 'a> { + iter: Chain, Difference<'a, T, S>>, +} + +impl<'a, T, S> Iterator for Union<'a, T, S> + where T: Eq + Hash, + S: BuildHasher, +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn fold(self, init: B, f: F) -> B + where F: FnMut(B, Self::Item) -> B + { + self.iter.fold(init, f) + } +} + +impl<'a, T, S> DoubleEndedIterator for Union<'a, T, S> + where T: Eq + Hash, + S: BuildHasher, +{ + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + + +impl<'a, 'b, T, S1, S2> BitAnd<&'b IndexSet> for &'a IndexSet + where T: Eq + Hash + Clone, + S1: BuildHasher + Default, + S2: BuildHasher, +{ + type Output = IndexSet; + + /// Returns the set intersection, cloned into a new set. + /// + /// Values are collected in the same order that they appear in `self`. + fn bitand(self, other: &'b IndexSet) -> Self::Output { + self.intersection(other).cloned().collect() + } +} + +impl<'a, 'b, T, S1, S2> BitOr<&'b IndexSet> for &'a IndexSet + where T: Eq + Hash + Clone, + S1: BuildHasher + Default, + S2: BuildHasher, +{ + type Output = IndexSet; + + /// Returns the set union, cloned into a new set. + /// + /// Values from `self` are collected in their original order, followed by + /// values that are unique to `other` in their original order. + fn bitor(self, other: &'b IndexSet) -> Self::Output { + self.union(other).cloned().collect() + } +} + +impl<'a, 'b, T, S1, S2> BitXor<&'b IndexSet> for &'a IndexSet + where T: Eq + Hash + Clone, + S1: BuildHasher + Default, + S2: BuildHasher, +{ + type Output = IndexSet; + + /// Returns the set symmetric-difference, cloned into a new set. + /// + /// Values from `self` are collected in their original order, followed by + /// values from `other` in their original order. + fn bitxor(self, other: &'b IndexSet) -> Self::Output { + self.symmetric_difference(other).cloned().collect() + } +} + +impl<'a, 'b, T, S1, S2> Sub<&'b IndexSet> for &'a IndexSet + where T: Eq + Hash + Clone, + S1: BuildHasher + Default, + S2: BuildHasher, +{ + type Output = IndexSet; + + /// Returns the set difference, cloned into a new set. + /// + /// Values are collected in the same order that they appear in `self`. + fn sub(self, other: &'b IndexSet) -> Self::Output { + self.difference(other).cloned().collect() + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use util::enumerate; + + #[test] + fn it_works() { + let mut set = IndexSet::new(); + assert_eq!(set.is_empty(), true); + set.insert(1); + set.insert(1); + assert_eq!(set.len(), 1); + assert!(set.get(&1).is_some()); + assert_eq!(set.is_empty(), false); + } + + #[test] + fn new() { + let set = IndexSet::::new(); + println!("{:?}", set); + assert_eq!(set.capacity(), 0); + assert_eq!(set.len(), 0); + assert_eq!(set.is_empty(), true); + } + + #[test] + fn insert() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5]; + let not_present = [1, 3, 6, 9, 10]; + let mut set = IndexSet::with_capacity(insert.len()); + + for (i, &elt) in enumerate(&insert) { + assert_eq!(set.len(), i); + set.insert(elt); + assert_eq!(set.len(), i + 1); + assert_eq!(set.get(&elt), Some(&elt)); + } + println!("{:?}", set); + + for &elt in ¬_present { + assert!(set.get(&elt).is_none()); + } + } + + #[test] + fn insert_full() { + let insert = vec![9, 2, 7, 1, 4, 6, 13]; + let present = vec![1, 6, 2]; + let mut set = IndexSet::with_capacity(insert.len()); + + for (i, &elt) in enumerate(&insert) { + assert_eq!(set.len(), i); + let (index, success) = set.insert_full(elt); + assert!(success); + assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0)); + assert_eq!(set.len(), i + 1); + } + + let len = set.len(); + for &elt in &present { + let (index, success) = set.insert_full(elt); + assert!(!success); + assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0)); + assert_eq!(set.len(), len); + } + } + + #[test] + fn insert_2() { + let mut set = IndexSet::with_capacity(16); + + let mut values = vec![]; + values.extend(0..16); + values.extend(128..267); + + for &i in &values { + let old_set = set.clone(); + set.insert(i); + for value in old_set.iter() { + if !set.get(value).is_some() { + println!("old_set: {:?}", old_set); + println!("set: {:?}", set); + panic!("did not find {} in set", value); + } + } + } + + for &i in &values { + assert!(set.get(&i).is_some(), "did not find {}", i); + } + } + + #[test] + fn insert_dup() { + let mut elements = vec![0, 2, 4, 6, 8]; + let mut set: IndexSet = elements.drain(..).collect(); + { + let (i, v) = set.get_full(&0).unwrap(); + assert_eq!(set.len(), 5); + assert_eq!(i, 0); + assert_eq!(*v, 0); + } + { + let inserted = set.insert(0); + let (i, v) = set.get_full(&0).unwrap(); + assert_eq!(set.len(), 5); + assert_eq!(inserted, false); + assert_eq!(i, 0); + assert_eq!(*v, 0); + } + } + + #[test] + fn insert_order() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut set = IndexSet::new(); + + for &elt in &insert { + set.insert(elt); + } + + assert_eq!(set.iter().count(), set.len()); + assert_eq!(set.iter().count(), insert.len()); + for (a, b) in insert.iter().zip(set.iter()) { + assert_eq!(a, b); + } + for (i, v) in (0..insert.len()).zip(set.iter()) { + assert_eq!(set.get_index(i).unwrap(), v); + } + } + + #[test] + fn grow() { + let insert = [0, 4, 2, 12, 8, 7, 11]; + let not_present = [1, 3, 6, 9, 10]; + let mut set = IndexSet::with_capacity(insert.len()); + + + for (i, &elt) in enumerate(&insert) { + assert_eq!(set.len(), i); + set.insert(elt); + assert_eq!(set.len(), i + 1); + assert_eq!(set.get(&elt), Some(&elt)); + } + + println!("{:?}", set); + for &elt in &insert { + set.insert(elt * 10); + } + for &elt in &insert { + set.insert(elt * 100); + } + for (i, &elt) in insert.iter().cycle().enumerate().take(100) { + set.insert(elt * 100 + i as i32); + } + println!("{:?}", set); + for &elt in ¬_present { + assert!(set.get(&elt).is_none()); + } + } + + #[test] + fn remove() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut set = IndexSet::new(); + + for &elt in &insert { + set.insert(elt); + } + + assert_eq!(set.iter().count(), set.len()); + assert_eq!(set.iter().count(), insert.len()); + for (a, b) in insert.iter().zip(set.iter()) { + assert_eq!(a, b); + } + + let remove_fail = [99, 77]; + let remove = [4, 12, 8, 7]; + + for &value in &remove_fail { + assert!(set.swap_remove_full(&value).is_none()); + } + println!("{:?}", set); + for &value in &remove { + //println!("{:?}", set); + let index = set.get_full(&value).unwrap().0; + assert_eq!(set.swap_remove_full(&value), Some((index, value))); + } + println!("{:?}", set); + + for value in &insert { + assert_eq!(set.get(value).is_some(), !remove.contains(value)); + } + assert_eq!(set.len(), insert.len() - remove.len()); + assert_eq!(set.iter().count(), insert.len() - remove.len()); + } + + #[test] + fn swap_remove_index() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut set = IndexSet::new(); + + for &elt in &insert { + set.insert(elt); + } + + let mut vector = insert.to_vec(); + let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1]; + + // check that the same swap remove sequence on vec and set + // have the same result. + for &rm in remove_sequence { + let out_vec = vector.swap_remove(rm); + let out_set = set.swap_remove_index(rm).unwrap(); + assert_eq!(out_vec, out_set); + } + assert_eq!(vector.len(), set.len()); + for (a, b) in vector.iter().zip(set.iter()) { + assert_eq!(a, b); + } + } + + #[test] + fn partial_eq_and_eq() { + let mut set_a = IndexSet::new(); + set_a.insert(1); + set_a.insert(2); + let mut set_b = set_a.clone(); + assert_eq!(set_a, set_b); + set_b.remove(&1); + assert_ne!(set_a, set_b); + + let set_c: IndexSet<_> = set_b.into_iter().collect(); + assert_ne!(set_a, set_c); + assert_ne!(set_c, set_a); + } + + #[test] + fn extend() { + let mut set = IndexSet::new(); + set.extend(vec![&1, &2, &3, &4]); + set.extend(vec![5, 6]); + assert_eq!(set.into_iter().collect::>(), vec![1, 2, 3, 4, 5, 6]); + } + + #[test] + fn comparisons() { + let set_a: IndexSet<_> = (0..3).collect(); + let set_b: IndexSet<_> = (3..6).collect(); + let set_c: IndexSet<_> = (0..6).collect(); + let set_d: IndexSet<_> = (3..9).collect(); + + assert!(!set_a.is_disjoint(&set_a)); + assert!(set_a.is_subset(&set_a)); + assert!(set_a.is_superset(&set_a)); + + assert!(set_a.is_disjoint(&set_b)); + assert!(set_b.is_disjoint(&set_a)); + assert!(!set_a.is_subset(&set_b)); + assert!(!set_b.is_subset(&set_a)); + assert!(!set_a.is_superset(&set_b)); + assert!(!set_b.is_superset(&set_a)); + + assert!(!set_a.is_disjoint(&set_c)); + assert!(!set_c.is_disjoint(&set_a)); + assert!(set_a.is_subset(&set_c)); + assert!(!set_c.is_subset(&set_a)); + assert!(!set_a.is_superset(&set_c)); + assert!(set_c.is_superset(&set_a)); + + assert!(!set_c.is_disjoint(&set_d)); + assert!(!set_d.is_disjoint(&set_c)); + assert!(!set_c.is_subset(&set_d)); + assert!(!set_d.is_subset(&set_c)); + assert!(!set_c.is_superset(&set_d)); + assert!(!set_d.is_superset(&set_c)); + } + + #[test] + fn iter_comparisons() { + use std::iter::empty; + + fn check<'a, I1, I2>(iter1: I1, iter2: I2) + where I1: Iterator, + I2: Iterator, + { + assert!(iter1.cloned().eq(iter2)); + } + + let set_a: IndexSet<_> = (0..3).collect(); + let set_b: IndexSet<_> = (3..6).collect(); + let set_c: IndexSet<_> = (0..6).collect(); + let set_d: IndexSet<_> = (3..9).rev().collect(); + + check(set_a.difference(&set_a), empty()); + check(set_a.symmetric_difference(&set_a), empty()); + check(set_a.intersection(&set_a), 0..3); + check(set_a.union(&set_a), 0..3); + + check(set_a.difference(&set_b), 0..3); + check(set_b.difference(&set_a), 3..6); + check(set_a.symmetric_difference(&set_b), 0..6); + check(set_b.symmetric_difference(&set_a), (3..6).chain(0..3)); + check(set_a.intersection(&set_b), empty()); + check(set_b.intersection(&set_a), empty()); + check(set_a.union(&set_b), 0..6); + check(set_b.union(&set_a), (3..6).chain(0..3)); + + check(set_a.difference(&set_c), empty()); + check(set_c.difference(&set_a), 3..6); + check(set_a.symmetric_difference(&set_c), 3..6); + check(set_c.symmetric_difference(&set_a), 3..6); + check(set_a.intersection(&set_c), 0..3); + check(set_c.intersection(&set_a), 0..3); + check(set_a.union(&set_c), 0..6); + check(set_c.union(&set_a), 0..6); + + check(set_c.difference(&set_d), 0..3); + check(set_d.difference(&set_c), (6..9).rev()); + check(set_c.symmetric_difference(&set_d), (0..3).chain((6..9).rev())); + check(set_d.symmetric_difference(&set_c), (6..9).rev().chain(0..3)); + check(set_c.intersection(&set_d), 3..6); + check(set_d.intersection(&set_c), (3..6).rev()); + check(set_c.union(&set_d), (0..6).chain((6..9).rev())); + check(set_d.union(&set_c), (3..9).rev().chain(0..3)); + } + + #[test] + fn ops() { + let empty = IndexSet::::new(); + let set_a: IndexSet<_> = (0..3).collect(); + let set_b: IndexSet<_> = (3..6).collect(); + let set_c: IndexSet<_> = (0..6).collect(); + let set_d: IndexSet<_> = (3..9).rev().collect(); + + assert_eq!(&set_a & &set_a, set_a); + assert_eq!(&set_a | &set_a, set_a); + assert_eq!(&set_a ^ &set_a, empty); + assert_eq!(&set_a - &set_a, empty); + + assert_eq!(&set_a & &set_b, empty); + assert_eq!(&set_b & &set_a, empty); + assert_eq!(&set_a | &set_b, set_c); + assert_eq!(&set_b | &set_a, set_c); + assert_eq!(&set_a ^ &set_b, set_c); + assert_eq!(&set_b ^ &set_a, set_c); + assert_eq!(&set_a - &set_b, set_a); + assert_eq!(&set_b - &set_a, set_b); + + assert_eq!(&set_a & &set_c, set_a); + assert_eq!(&set_c & &set_a, set_a); + assert_eq!(&set_a | &set_c, set_c); + assert_eq!(&set_c | &set_a, set_c); + assert_eq!(&set_a ^ &set_c, set_b); + assert_eq!(&set_c ^ &set_a, set_b); + assert_eq!(&set_a - &set_c, empty); + assert_eq!(&set_c - &set_a, set_b); + + assert_eq!(&set_c & &set_d, set_b); + assert_eq!(&set_d & &set_c, set_b); + assert_eq!(&set_c | &set_d, &set_a | &set_d); + assert_eq!(&set_d | &set_c, &set_a | &set_d); + assert_eq!(&set_c ^ &set_d, &set_a | &(&set_d - &set_b)); + assert_eq!(&set_d ^ &set_c, &set_a | &(&set_d - &set_b)); + assert_eq!(&set_c - &set_d, set_a); + assert_eq!(&set_d - &set_c, &set_d - &set_b); + } +} diff --git a/vendor/indexmap/src/util.rs b/vendor/indexmap/src/util.rs new file mode 100644 index 0000000000..90d3e7e334 --- /dev/null +++ b/vendor/indexmap/src/util.rs @@ -0,0 +1,17 @@ + +use std::iter::Enumerate; +use std::mem::size_of; + +pub fn third(t: (A, B, C)) -> C { t.2 } + +pub fn enumerate(iterable: I) -> Enumerate + where I: IntoIterator +{ + iterable.into_iter().enumerate() +} + +/// return the number of steps from a to b +pub fn ptrdistance(a: *const T, b: *const T) -> usize { + debug_assert!(a as usize <= b as usize); + (b as usize - a as usize) / size_of::() +} diff --git a/vendor/indexmap/tests/equivalent_trait.rs b/vendor/indexmap/tests/equivalent_trait.rs new file mode 100644 index 0000000000..8b79e20a19 --- /dev/null +++ b/vendor/indexmap/tests/equivalent_trait.rs @@ -0,0 +1,55 @@ + +#[macro_use] extern crate indexmap; + +use indexmap::Equivalent; + +use std::hash::Hash; + +#[derive(Debug, Hash)] +pub struct Pair(pub A, pub B); + +impl PartialEq<(A, B)> for Pair + where C: PartialEq, + D: PartialEq, +{ + fn eq(&self, rhs: &(A, B)) -> bool { + self.0 == rhs.0 && + self.1 == rhs.1 && + true + } +} + +impl Equivalent for Pair + where Pair: PartialEq, + A: Hash + Eq, + B: Hash + Eq, +{ + fn equivalent(&self, other: &X) -> bool { + *self == *other + } +} + +#[test] +fn test_lookup() { + let s = String::from; + let map = indexmap! { + (s("a"), s("b")) => 1, + (s("a"), s("x")) => 2, + }; + + assert!(map.contains_key(&Pair("a", "b"))); + assert!(!map.contains_key(&Pair("b", "a"))); +} + +#[test] +fn test_string_str() { + let s = String::from; + let mut map = indexmap! { + s("a") => 1, s("b") => 2, + s("x") => 3, s("y") => 4, + }; + + assert!(map.contains_key("a")); + assert!(!map.contains_key("z")); + assert_eq!(map.remove("b"), Some(2)); +} diff --git a/vendor/indexmap/tests/quick.rs b/vendor/indexmap/tests/quick.rs new file mode 100644 index 0000000000..14f267cff1 --- /dev/null +++ b/vendor/indexmap/tests/quick.rs @@ -0,0 +1,365 @@ + +extern crate indexmap; +extern crate itertools; +#[macro_use] +extern crate quickcheck; + +extern crate fnv; + +use indexmap::IndexMap; +use itertools::Itertools; + +use quickcheck::Arbitrary; +use quickcheck::Gen; + +use fnv::FnvHasher; +use std::hash::{BuildHasher, BuildHasherDefault}; +type FnvBuilder = BuildHasherDefault; +type OrderMapFnv = IndexMap; + +use std::collections::HashSet; +use std::collections::HashMap; +use std::iter::FromIterator; +use std::hash::Hash; +use std::fmt::Debug; +use std::ops::Deref; +use std::cmp::min; + + +use indexmap::map::Entry as OEntry; +use std::collections::hash_map::Entry as HEntry; + + +fn set<'a, T: 'a, I>(iter: I) -> HashSet + where I: IntoIterator, + T: Copy + Hash + Eq +{ + iter.into_iter().cloned().collect() +} + +fn indexmap<'a, T: 'a, I>(iter: I) -> IndexMap + where I: IntoIterator, + T: Copy + Hash + Eq, +{ + IndexMap::from_iter(iter.into_iter().cloned().map(|k| (k, ()))) +} + +quickcheck! { + fn contains(insert: Vec) -> bool { + let mut map = IndexMap::new(); + for &key in &insert { + map.insert(key, ()); + } + insert.iter().all(|&key| map.get(&key).is_some()) + } + + fn contains_not(insert: Vec, not: Vec) -> bool { + let mut map = IndexMap::new(); + for &key in &insert { + map.insert(key, ()); + } + let nots = &set(¬) - &set(&insert); + nots.iter().all(|&key| map.get(&key).is_none()) + } + + fn insert_remove(insert: Vec, remove: Vec) -> bool { + let mut map = IndexMap::new(); + for &key in &insert { + map.insert(key, ()); + } + for &key in &remove { + map.swap_remove(&key); + } + let elements = &set(&insert) - &set(&remove); + map.len() == elements.len() && map.iter().count() == elements.len() && + elements.iter().all(|k| map.get(k).is_some()) + } + + fn insertion_order(insert: Vec) -> bool { + let mut map = IndexMap::new(); + for &key in &insert { + map.insert(key, ()); + } + itertools::assert_equal(insert.iter().unique(), map.keys()); + true + } + + fn pop(insert: Vec) -> bool { + let mut map = IndexMap::new(); + for &key in &insert { + map.insert(key, ()); + } + let mut pops = Vec::new(); + while let Some((key, _v)) = map.pop() { + pops.push(key); + } + pops.reverse(); + + itertools::assert_equal(insert.iter().unique(), &pops); + true + } + + fn with_cap(cap: usize) -> bool { + let map: IndexMap = IndexMap::with_capacity(cap); + println!("wish: {}, got: {} (diff: {})", cap, map.capacity(), map.capacity() as isize - cap as isize); + map.capacity() >= cap + } + + fn drain(insert: Vec) -> bool { + let mut map = IndexMap::new(); + for &key in &insert { + map.insert(key, ()); + } + let mut clone = map.clone(); + let drained = clone.drain(..); + for (key, _) in drained { + map.remove(&key); + } + map.is_empty() + } +} + +use Op::*; +#[derive(Copy, Clone, Debug)] +enum Op { + Add(K, V), + Remove(K), + AddEntry(K, V), + RemoveEntry(K), +} + +impl Arbitrary for Op + where K: Arbitrary, + V: Arbitrary, +{ + fn arbitrary(g: &mut G) -> Self { + match g.gen::() % 4 { + 0 => Add(K::arbitrary(g), V::arbitrary(g)), + 1 => AddEntry(K::arbitrary(g), V::arbitrary(g)), + 2 => Remove(K::arbitrary(g)), + _ => RemoveEntry(K::arbitrary(g)), + } + } +} + +fn do_ops(ops: &[Op], a: &mut IndexMap, b: &mut HashMap) + where K: Hash + Eq + Clone, + V: Clone, + S: BuildHasher, +{ + for op in ops { + match *op { + Add(ref k, ref v) => { + a.insert(k.clone(), v.clone()); + b.insert(k.clone(), v.clone()); + } + AddEntry(ref k, ref v) => { + a.entry(k.clone()).or_insert(v.clone()); + b.entry(k.clone()).or_insert(v.clone()); + } + Remove(ref k) => { + a.swap_remove(k); + b.remove(k); + } + RemoveEntry(ref k) => { + match a.entry(k.clone()) { + OEntry::Occupied(ent) => { ent.remove_entry(); }, + _ => { } + } + match b.entry(k.clone()) { + HEntry::Occupied(ent) => { ent.remove_entry(); }, + _ => { } + } + } + } + //println!("{:?}", a); + } +} + +fn assert_maps_equivalent(a: &IndexMap, b: &HashMap) -> bool + where K: Hash + Eq + Debug, + V: Eq + Debug, +{ + assert_eq!(a.len(), b.len()); + assert_eq!(a.iter().next().is_some(), b.iter().next().is_some()); + for key in a.keys() { + assert!(b.contains_key(key), "b does not contain {:?}", key); + } + for key in b.keys() { + assert!(a.get(key).is_some(), "a does not contain {:?}", key); + } + for key in a.keys() { + assert_eq!(a[key], b[key]); + } + true +} + +quickcheck! { + fn operations_i8(ops: Large>>) -> bool { + let mut map = IndexMap::new(); + let mut reference = HashMap::new(); + do_ops(&ops, &mut map, &mut reference); + assert_maps_equivalent(&map, &reference) + } + + fn operations_string(ops: Vec>) -> bool { + let mut map = IndexMap::new(); + let mut reference = HashMap::new(); + do_ops(&ops, &mut map, &mut reference); + assert_maps_equivalent(&map, &reference) + } + + fn keys_values(ops: Large>>) -> bool { + let mut map = IndexMap::new(); + let mut reference = HashMap::new(); + do_ops(&ops, &mut map, &mut reference); + let mut visit = IndexMap::new(); + for (k, v) in map.keys().zip(map.values()) { + assert_eq!(&map[k], v); + assert!(!visit.contains_key(k)); + visit.insert(*k, *v); + } + assert_eq!(visit.len(), reference.len()); + true + } + + fn keys_values_mut(ops: Large>>) -> bool { + let mut map = IndexMap::new(); + let mut reference = HashMap::new(); + do_ops(&ops, &mut map, &mut reference); + let mut visit = IndexMap::new(); + let keys = Vec::from_iter(map.keys().cloned()); + for (k, v) in keys.iter().zip(map.values_mut()) { + assert_eq!(&reference[k], v); + assert!(!visit.contains_key(k)); + visit.insert(*k, *v); + } + assert_eq!(visit.len(), reference.len()); + true + } + + fn equality(ops1: Vec>, removes: Vec) -> bool { + let mut map = IndexMap::new(); + let mut reference = HashMap::new(); + do_ops(&ops1, &mut map, &mut reference); + let mut ops2 = ops1.clone(); + for &r in &removes { + if !ops2.is_empty() { + let i = r % ops2.len(); + ops2.remove(i); + } + } + let mut map2 = OrderMapFnv::default(); + let mut reference2 = HashMap::new(); + do_ops(&ops2, &mut map2, &mut reference2); + assert_eq!(map == map2, reference == reference2); + true + } + + fn retain_ordered(keys: Large>, remove: Large>) -> () { + let mut map = indexmap(keys.iter()); + let initial_map = map.clone(); // deduplicated in-order input + let remove_map = indexmap(remove.iter()); + let keys_s = set(keys.iter()); + let remove_s = set(remove.iter()); + let answer = &keys_s - &remove_s; + map.retain(|k, _| !remove_map.contains_key(k)); + + // check the values + assert_eq!(map.len(), answer.len()); + for key in &answer { + assert!(map.contains_key(key)); + } + // check the order + itertools::assert_equal(map.keys(), initial_map.keys().filter(|&k| !remove_map.contains_key(k))); + } + + fn sort_1(keyvals: Large>) -> () { + let mut map: IndexMap<_, _> = IndexMap::from_iter(keyvals.to_vec()); + let mut answer = keyvals.0; + answer.sort_by_key(|t| t.0); + + // reverse dedup: Because IndexMap::from_iter keeps the last value for + // identical keys + answer.reverse(); + answer.dedup_by_key(|t| t.0); + answer.reverse(); + + map.sort_by(|k1, _, k2, _| Ord::cmp(k1, k2)); + + // check it contains all the values it should + for &(key, val) in &answer { + assert_eq!(map[&key], val); + } + + // check the order + + let mapv = Vec::from_iter(map); + assert_eq!(answer, mapv); + + } + + fn sort_2(keyvals: Large>) -> () { + let mut map: IndexMap<_, _> = IndexMap::from_iter(keyvals.to_vec()); + map.sort_by(|_, v1, _, v2| Ord::cmp(v1, v2)); + assert_sorted_by_key(map, |t| t.1); + } +} + +fn assert_sorted_by_key(iterable: I, key: Key) + where I: IntoIterator, + I::Item: Ord + Clone + Debug, + Key: Fn(&I::Item) -> X, + X: Ord, +{ + let input = Vec::from_iter(iterable); + let mut sorted = input.clone(); + sorted.sort_by_key(key); + assert_eq!(input, sorted); +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +struct Alpha(String); + +impl Deref for Alpha { + type Target = String; + fn deref(&self) -> &String { &self.0 } +} + +const ALPHABET: &'static [u8] = b"abcdefghijklmnopqrstuvwxyz"; + +impl Arbitrary for Alpha { + fn arbitrary(g: &mut G) -> Self { + let len = g.next_u32() % g.size() as u32; + let len = min(len, 16); + Alpha((0..len).map(|_| { + ALPHABET[g.next_u32() as usize % ALPHABET.len()] as char + }).collect()) + } + + fn shrink(&self) -> Box> { + Box::new((**self).shrink().map(Alpha)) + } +} + +/// quickcheck Arbitrary adaptor -- make a larger vec +#[derive(Clone, Debug)] +struct Large(T); + +impl Deref for Large { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Arbitrary for Large> + where T: Arbitrary +{ + fn arbitrary(g: &mut G) -> Self { + let len = g.next_u32() % (g.size() * 10) as u32; + Large((0..len).map(|_| T::arbitrary(g)).collect()) + } + + fn shrink(&self) -> Box> { + Box::new((**self).shrink().map(Large)) + } +} diff --git a/vendor/indexmap/tests/serde.rs b/vendor/indexmap/tests/serde.rs new file mode 100644 index 0000000000..dbb23573e4 --- /dev/null +++ b/vendor/indexmap/tests/serde.rs @@ -0,0 +1,59 @@ +#![cfg(feature = "serde-1")] + +#[macro_use] +extern crate indexmap; +extern crate serde_test; +extern crate fnv; + +use serde_test::{Token, assert_tokens}; + +#[test] +fn test_serde() { + let map = indexmap! { 1 => 2, 3 => 4 }; + assert_tokens(&map, + &[Token::Map { len: Some(2) }, + Token::I32(1), + Token::I32(2), + Token::I32(3), + Token::I32(4), + Token::MapEnd]); +} + +#[test] +fn test_serde_set() { + let set = indexset! { 1, 2, 3, 4 }; + assert_tokens(&set, + &[Token::Seq { len: Some(4) }, + Token::I32(1), + Token::I32(2), + Token::I32(3), + Token::I32(4), + Token::SeqEnd]); +} + +#[test] +fn test_serde_fnv_hasher() { + let mut map: ::indexmap::IndexMap = Default::default(); + map.insert(1, 2); + map.insert(3, 4); + assert_tokens(&map, + &[Token::Map { len: Some(2) }, + Token::I32(1), + Token::I32(2), + Token::I32(3), + Token::I32(4), + Token::MapEnd]); +} + +#[test] +fn test_serde_map_fnv_hasher() { + let mut set: ::indexmap::IndexSet = Default::default(); + set.extend(1..5); + assert_tokens(&set, + &[Token::Seq { len: Some(4) }, + Token::I32(1), + Token::I32(2), + Token::I32(3), + Token::I32(4), + Token::SeqEnd]); +} diff --git a/vendor/indexmap/tests/tests.rs b/vendor/indexmap/tests/tests.rs new file mode 100644 index 0000000000..4a7f4db7a4 --- /dev/null +++ b/vendor/indexmap/tests/tests.rs @@ -0,0 +1,32 @@ + +#[macro_use] +extern crate indexmap; +extern crate itertools; + + +#[test] +fn test_sort() { + let m = indexmap! { + 1 => 2, + 7 => 1, + 2 => 2, + 3 => 3, + }; + + itertools::assert_equal(m.sorted_by(|_k1, v1, _k2, v2| v1.cmp(v2)), + vec![(7, 1), (1, 2), (2, 2), (3, 3)]); +} + + +#[test] +fn test_sort_set() { + let s = indexset! { + 1, + 7, + 2, + 3, + }; + + itertools::assert_equal(s.sorted_by(|v1, v2| v1.cmp(v2)), + vec![1, 2, 3, 7]); +} diff --git a/vendor/itertools-0.7.8/.cargo-checksum.json b/vendor/itertools-0.7.8/.cargo-checksum.json deleted file mode 100644 index 62356fd10b..0000000000 --- a/vendor/itertools-0.7.8/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"aeaa15ad23357fa2c222b01f8cbb4f6efc61dc1f0e8687beee211d0eeb3b1d1e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","Makefile":"13f1c5b88a7b946b5813f7231df2933b6b19b223e9e2d3fa63ad681192f984b5","README.rst":"711bd98258ffea2d19fe96e4c766aca622fbf395bc5a7c8f6cad52ac65121464","benches/bench1.rs":"695e4b00addf2e8e44a09d85a588cb333c97109829e59739bdab01e7342d47b5","benches/extra/mod.rs":"4c5b03e74fc5b02383500c9da9fd6550262706ee569d70d085700f6d0b5749ba","benches/extra/zipslices.rs":"108dd488de366b2d83fb6bcc603ecbf9a017e165ac19d03440074fa244af3fb2","benches/tree_fold1.rs":"84cddbabb1a681f3196430a8e27b060103366143a3ee4c42c3b0628fc00a7543","benches/tuple_combinations.rs":"8c14e9341d92e5cfd5f9a067d11088b37b003e82635d1ab3a8e5290e3ef83eed","benches/tuples.rs":"412a952f08bb03695952d5cfd57949dcf28be8b99e3c6653994bdb8af9654653","bors.toml":"eed8564cdc475f30ff4147781c5e50176b3048b5d24b272d1354dad952fd00be","custom.css":"03d2316d325a09f03f0fae54d24b64f784518a8249432edbd60e01436be900d5","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"3996ca0a62762aec2b102f0f4244fe90d4b4354286d68d80cdc40e35f4352ba3","src/adaptors/mod.rs":"ba6f96d594461c82d67e6c60770ebcb82e80948d28827b5eb613a7072ad8a0eb","src/adaptors/multi_product.rs":"bb239555be38cde1f419bacfd09728f6ccaf51b6b4811c266b5677705175e685","src/combinations.rs":"a9a3fc78eb5c9f3933ff60275a635d0c81f4864a73515dc052aeb2add4ad4909","src/concat_impl.rs":"276339b00588f54c25f8ffbe0ae3c0031f7e52fb53c6578554a0bde1681b58a5","src/cons_tuples_impl.rs":"87c620d2ffdd3475218f5f493dbef601491be9f6cdfe57c44929449b32e6709f","src/diff.rs":"921e2b867d7b32ffedc72a5eb780811322d14d1e0883a608b9028a2afcad0df2","src/either_or_both.rs":"4739b8644fa932b7992e565be6a6bc64dff9f93e345c52f90b3e1f8a67e6d18e","src/format.rs":"412fbe02f12311c6fbcec1044f57ad6991783f5a3f323b9c391accfe4915106f","src/free.rs":"ced78d79c0c78398ac53bf628e77ae84f214972d0dad0507b6687c2f88873aaa","src/group_map.rs":"872d6e243e649ad30c94973c034596cc3377b10018e361bca07e11c612006de6","src/groupbylazy.rs":"a067a12671be9ae05a9152518103f39f7286fde09f758de8af75a1064a3b5567","src/impl_macros.rs":"eb0bb3f70ec1bcaffa6110ae4134c777951ed1e5f48d8c811dbf0a597dc48faa","src/intersperse.rs":"9c18f239654ebfcce1d68a0256d2df6d79a2b8c4fb5df87d67e2ebe04a07e1a9","src/kmerge_impl.rs":"51e71d3e76670a8efb16597a9224d2c9b40cee6bc6270d06b66aadafea6dc26b","src/lib.rs":"d641c89cbe827bf88902dda7af20f1de7b3325a5e857f95181737cbb9afc0692","src/merge_join.rs":"98e6fcc761a558ad21789efe041c3f90e62f6c75e05840670df45ad4f9b07e1f","src/minmax.rs":"4668a7f824fbc133599f43ffb6f7283e5bd603e07df2d8176abc6f25d6af9db0","src/multipeek_impl.rs":"ebe9544d94d0bf7200f7625241a3b5a291b7b564091a08cad40ff08b51f1b1bf","src/pad_tail.rs":"078615a2892f8c6db665074cf6f1be1bef4cf5ee418bc174edcfd4dc703e163f","src/peeking_take_while.rs":"6aea3bb40fb480e9f3695ce2a7a3a2e2346d437ca846d20e6bb3c09beb0934f4","src/process_results_impl.rs":"5f454cf62ceb82cab7c08c0c190de3ae083e219a8acc7a1a22f17eec9cfcd65c","src/put_back_n_impl.rs":"d35858184c525372b22d14d42cdf63726cf0fd50f5bd42ec7a82d55a8e180e9f","src/rciter_impl.rs":"8f51abc7e1ae3320cc5d56fadd66f880a7a06773be656bd8c4712357f01ae1d9","src/repeatn.rs":"4bd1782364b16105fbef3f3de7bf62780710e5c996db44a00e4b5f16c2625d86","src/size_hint.rs":"c1d35b422a696cf3d63e7c90d8f9fdf01a304cf8156e914287c4ef48fea62dd3","src/sources.rs":"9d7eb4dbd87f659d04b4980238c5fc72b71472e16861d17a32cab9b77a3df06a","src/tee.rs":"59cf9ef0b41882307ea1e3503a2ff351f401f4c43d95acf423a990b0bf0e29ae","src/tuple_impl.rs":"0c7f907e85d2ef0661583b36c7b8a7341b8feadafe28d10539a211dff5c028ea","src/unique_impl.rs":"63db2d720ff5e3d9c0d6c2b245ffff25d4040e4fcbcb2a6524b0f912826f86af","src/with_position.rs":"d922f045f6fa090a431be928f3221c6dc37ac6f9bb54461b3b84f99a7e91244a","src/zip_eq_impl.rs":"f857c69120255db16ad6ddec628c79cb573b1d5179fcebab1906bf5b762c02e3","src/zip_longest.rs":"375325ef069970e6fb83c6097c2824877bb0f06e4f1e664e4fe681804abe003c","src/ziptuple.rs":"d7ae7d3c33185ad74ab2bba750ac337b5c236750cc8341dd9883faf6465712a1","tests/merge_join.rs":"546eaffae40010f15a7bcf95bc53f5e9b67424c5b93df6ffb0aaa1e48e8b90c0","tests/peeking_take_while.rs":"a2ae6474e09620a47bb8a6e3c62929261e72c52881370adb2d22e89aa9e9aec8","tests/quick.rs":"24b1ecc7522353d9fb278cb4fa4810437c717ff8a5a2a95e08909511420fc514","tests/test_core.rs":"ec9b8b8227170060a7828e907d6750c7123b4a1618073ac10e2b3fca72bd50d7","tests/test_std.rs":"63a5e52953e7209f72bdfd157047ee7b93a696786d1b39931a3f8a1053a67128","tests/tuples.rs":"5323d15a7abf6545b2655167d3206b6cf6a947e9409a244ea6a8cf4ad8ceac64","tests/zip.rs":"fe213d70c4fa114cb4d1930a6b971f4af617a239041ddb87e6b5a9bbe62261b8"},"package":"f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"} \ No newline at end of file diff --git a/vendor/itertools-0.7.8/Cargo.toml b/vendor/itertools-0.7.8/Cargo.toml deleted file mode 100644 index fc2b0cb51d..0000000000 --- a/vendor/itertools-0.7.8/Cargo.toml +++ /dev/null @@ -1,43 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "itertools" -version = "0.7.8" -authors = ["bluss"] -description = "Extra iterator adaptors, iterator methods, free functions, and macros." -documentation = "https://docs.rs/itertools/" -keywords = ["iterator", "data-structure", "zip", "product", "group-by"] -categories = ["algorithms", "rust-patterns"] -license = "MIT/Apache-2.0" -repository = "https://github.com/bluss/rust-itertools" -[package.metadata.release] -no-dev-version = true -[profile.bench] -debug = true - -[lib] -test = false -bench = false -[dependencies.either] -version = "1.0" -default-features = false -[dev-dependencies.permutohedron] -version = "0.2" - -[dev-dependencies.quickcheck] -version = "0.5" -default-features = false - -[features] -default = ["use_std"] -use_std = [] diff --git a/vendor/itertools-0.7.8/Makefile b/vendor/itertools-0.7.8/Makefile deleted file mode 100644 index bb03984248..0000000000 --- a/vendor/itertools-0.7.8/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -DOCCRATES = itertools - -# deps to delete the generated docs -RMDOCS = - -FEATURES = - -VERSIONS = $(patsubst %,target/VERS/%,$(DOCCRATES)) - -docs: mkdocs subst $(RMDOCS) - -# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html -$(VERSIONS): Cargo.toml - mkdir -p $(@D) - cargo pkgid $(@F) | sed -e "s/.*#\(\|.*:\)//" > "$@" - -$(DOCCRATES): %: target/VERS/% - # Put in the crate version into the docs - find ./doc/$@ -name "*.html" -exec sed -i -e "s/\(.*\) - Rust/<title>$@ $(shell cat $<) - \1 - Rust/g" {} \; - -subst: $(DOCCRATES) - -mkdocs: Cargo.toml - cargo doc --features=$(FEATURES) --no-deps - rm -rf ./doc - cp -r ./target/doc ./doc - - cat ./custom.css >> doc/main.css - -$(RMDOCS): mkdocs - rm -r ./doc/$@ - sed -i "/searchIndex\['$@'\]/d" doc/search-index.js - - -.PHONY: docs mkdocs subst $(DOCCRATES) $(RMDOCS) diff --git a/vendor/itertools-0.7.8/README.rst b/vendor/itertools-0.7.8/README.rst deleted file mode 100644 index b2a549ee73..0000000000 --- a/vendor/itertools-0.7.8/README.rst +++ /dev/null @@ -1,490 +0,0 @@ - -Itertools -========= - -Extra iterator adaptors, functions and macros. - -Please read the `API documentation here`__ - -__ https://docs.rs/itertools/ - -|build_status|_ |crates|_ - -.. |build_status| image:: https://travis-ci.org/bluss/rust-itertools.svg?branch=master -.. _build_status: https://travis-ci.org/bluss/rust-itertools - -.. |crates| image:: http://meritbadge.herokuapp.com/itertools -.. _crates: https://crates.io/crates/itertools - -How to use with cargo: - -.. code:: toml - - [dependencies] - itertools = "0.7.3" - -How to use in your crate: - -.. code:: rust - - #[macro_use] extern crate itertools; - - use itertools::Itertools; - -How to contribute: - -- Fix a bug or implement a new thing -- Include tests for your new feature, preferably a quickcheck test -- Make a Pull Request - - -Recent Changes --------------- - -- 0.7.8 - - - Add new iterator method ``.tree_fold1()`` which is like ``.fold1()`` - except items are combined in a tree structure (see its docs). - By @scottmcm - - Add more ``Debug`` impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy, - ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee, - ZipLongest, ZipEq, Zip. - -- 0.7.7 - - - Add new iterator method ``.into_group_map() -> HashMap<K, Vec<V>>`` - which turns an iterator of ``(K, V)`` elements into such a hash table, - where values are grouped by key. By @tobz1000 - - Add new free function ``flatten`` for the ``.flatten()`` adaptor. - **NOTE:** recent Rust nightlies have ``Iterator::flatten`` and thus a clash - with our flatten adaptor. One workaround is to use the itertools ``flatten`` - free function. - -- 0.7.6 - - - Add new adaptor ``.multi_cartesian_product()`` which is an n-ary product - iterator by @tobz1000 - - Add new method ``.sorted_by_key()`` by @Xion - - Provide simpler and faster ``.count()`` for ``.unique()`` and ``.unique_by()`` - -- 0.7.5 - - - ``.multipeek()`` now implements ``PeekingNext``, by @nicopap. - -- 0.7.4 - - - Add new adaptor ``.update()`` by @lucasem; this adaptor is used - to modify an element before passing it on in an iterator chain. - -- 0.7.3 - - - Add new method ``.collect_tuple()`` by @matklad; it makes a tuple out of - the iterator's elements if the number of them matches **exactly**. - - Implement ``fold`` and ``collect`` for ``.map_results()`` which means - it reuses the code of the standard ``.map()`` for these methods. - -- 0.7.2 - - - Add new adaptor ``.merge_join_by`` by @srijs; a heterogeneous merge join - for two ordered sequences. - -- 0.7.1 - - - Iterator adaptors and iterators in itertools now use the same ``must_use`` - reminder that the standard library adaptors do, by @matematikaedit and @bluss - *“iterator adaptors are lazy and do nothing unless consumed”*. - -- 0.7.0 - - - Faster ``izip!()`` by @krdln - - - ``izip!()`` is now a wrapper for repeated regular ``.zip()`` and - a single ``.map()``. This means it optimizes as well as the standard - library ``.zip()`` it uses. - **Note:** ``multizip`` and ``izip!()`` are now different! The former - has a named type but the latter optimizes better. - - - Faster ``.unique()`` - - - ``no_std`` support, which is opt-in! - - - Many lovable features are still there without std, like ``izip!()`` - or ``.format()`` or ``.merge()``, but not those that use collections. - - - Trait bounds were required up front instead of just on the type: - ``group_by``'s ``PartialEq`` by @Phlosioneer and ``repeat_call``'s - ``FnMut``. - - Removed deprecated constructor ``Zip::new`` — use ``izip!()`` or ``multizip()`` - -- 0.6.5 - - - Fix bug in ``.cartesian_product()``'s fold (which only was visible for - unfused iterators). - -- 0.6.4 - - - Add specific ``fold`` implementations for ``.cartesian_product()`` and - ``cons_tuples()``, which improves their performance in fold, foreach, and - iterator consumers derived from them. - -- 0.6.3 - - - Add iterator adaptor ``.positions(predicate)`` by @tmccombs - -- 0.6.2 - - - Add function ``process_results`` which can “lift” a function of the regular - values of an iterator so that it can process the ``Ok`` values from an - iterator of ``Results`` instead, by @shepmaster - - Add iterator method ``.concat()`` which combines all iterator elements - into a single collection using the ``Extend`` trait, by @srijs - -- 0.6.1 - - - Better size hint testing and subsequent size hint bugfixes by @rkarp. - Fixes bugs in product, interleave_shortest size hints. - - New iterator method ``.all_equal()`` by @phimuemue - -- 0.6.0 - - - Deprecated names were removed in favour of their replacements - - ``.flatten()`` does not implement double ended iteration anymore - - ``.fold_while()`` uses ``&mut self`` and returns ``FoldWhile<T>``, for - composability (#168) - - ``.foreach()`` and ``.fold1()`` use ``self``, like ``.fold()`` does. - - ``.combinations(0)`` now produces a single empty vector. (#174) - -- 0.5.10 - - - Add itertools method ``.kmerge_by()`` (and corresponding free function) - - Relaxed trait requirement of ``.kmerge()`` and ``.minmax()`` to PartialOrd. - -- 0.5.9 - - - Add multipeek method ``.reset_peek()`` - - Add categories - -- 0.5.8 - - - Add iterator adaptor ``.peeking_take_while()`` and its trait ``PeekingNext``. - -- 0.5.7 - - - Add iterator adaptor ``.with_position()`` - - Fix multipeek's performance for long peeks by using ``VecDeque``. - -- 0.5.6 - - - Add ``.map_results()`` - -- 0.5.5 - - - Many more adaptors now implement ``Debug`` - - Add free function constructor ``repeat_n``. ``RepeatN::new`` is now - deprecated. - -- 0.5.4 - - - Add infinite generator function ``iterate``, that takes a seed and a - closure. - -- 0.5.3 - - - Special-cased ``.fold()`` for flatten and put back. ``.foreach()`` - now uses fold on the iterator, to pick up any iterator specific loop - implementation. - - ``.combinations(n)`` asserts up front that ``n != 0``, instead of - running into an error on the second iterator element. - -- 0.5.2 - - - Add ``.tuples::<T>()`` that iterates by two, three or four elements at - a time (where ``T`` is a tuple type). - - Add ``.tuple_windows::<T>()`` that iterates using a window of the - two, three or four most recent elements. - - Add ``.next_tuple::<T>()`` method, that picks the next two, three or four - elements in one go. - - ``.interleave()`` now has an accurate size hint. - -- 0.5.1 - - - Workaround module/function name clash that made racer crash on completing - itertools. Only internal changes needed. - -- 0.5.0 - - - `Release announcement <http://bluss.github.io/rust/2016/09/26/itertools-0.5.0/>`_ - - Renamed: - - - combinations is now tuple_combinations - - combinations_n to combinations - - group_by_lazy, chunks_lazy to group_by, chunks - - Unfold::new to unfold() - - RepeatCall::new to repeat_call() - - Zip::new to multizip - - PutBack::new, PutBackN::new to put_back, put_back_n - - PutBack::with_value is now a builder setter, not a constructor - - MultiPeek::new, .multipeek() to multipeek() - - format to format_with and format_default to format - - .into_rc() to rciter - - ``Partition`` enum is now ``Either`` - - - Module reorganization: - - - All iterator structs are under ``itertools::structs`` but also - reexported to the top level, for backwards compatibility - - All free functions are reexported at the root, ``itertools::free`` will - be removed in the next version - - - Removed: - - - ZipSlices, use .zip() instead - - .enumerate_from(), ZipTrusted, due to being unstable - - .mend_slices(), moved to crate odds - - Stride, StrideMut, moved to crate odds - - linspace(), moved to crate itertools-num - - .sort_by(), use .sorted_by() - - .is_empty_hint(), use .size_hint() - - .dropn(), use .dropping() - - .map_fn(), use .map() - - .slice(), use .take() / .skip() - - helper traits in misc - - ``new`` constructors on iterator structs, use Itertools trait or free - functions instead - - ``itertools::size_hint`` is now private - - - Behaviour changes: - - - format and format_with helpers now panic if you try to format them more - than once. - - ``repeat_call`` is not double ended anymore - - - New features: - - - tuple flattening iterator is constructible with ``cons_tuples`` - - itertools reexports ``Either`` from the ``either`` crate. ``Either<L, R>`` - is an iterator when ``L, R`` are. - - ``MinMaxResult`` now implements Copy and Clone - - tuple_combinations supports 1-4 tuples of combinations (previously just 2) - -- 0.4.19 - - - Add ``.minmax_by()`` - - Add ``itertools::free::cloned`` - - Add ``itertools::free::rciter`` - - Improve ``.step(n)`` slightly to take advantage of specialized Fuse better. - -- 0.4.18 - - - Only changes related to the "unstable" crate feature. This feature is more - or less deprecated. - - - Use deprecated warnings when unstable is enabled. .enumerate_from() will - be removed imminently since it's using a deprecated libstd trait. - -- 0.4.17 - - - Fix bug in .kmerge() that caused it to often produce the wrong order (#134) - -- 0.4.16 - - - Improve precision of the interleave_shortest adaptor's size hint (it is - now computed exactly when possible). - -- 0.4.15 - - - Fixup on top of the workaround in 0.4.14. A function in itertools::free was - removed by mistake and now it is added back again. - -- 0.4.14 - - - Workaround an upstream regression in a rust nightly build that broke - compilation of of itertools::free::{interleave, merge} - -- 0.4.13 - - - Add .minmax() and .minmax_by_key(), iterator methods for finding both minimum - and maximum in one scan. - - Add .format_default(), a simpler version of .format() (lazy formatting - for iterators). - -- 0.4.12 - - - Add .zip_eq(), an adaptor like .zip() except it ensures iterators - of inequal length don't pass silently (instead it panics). - - Add .fold_while(), an iterator method that is a fold that - can short-circuit. - - Add .partition_map(), an iterator method that can separate elements - into two collections. - -- 0.4.11 - - - Add .get() for Stride{,Mut} and .get_mut() for StrideMut - -- 0.4.10 - - - Improve performance of .kmerge() - -- 0.4.9 - - - Add k-ary merge adaptor .kmerge() - - Fix a bug in .islice() with ranges a..b where a > b. - -- 0.4.8 - - - Implement Clone, Debug for Linspace - -- 0.4.7 - - - Add function diff_with() that compares two iterators - - Add .combinations_n(), an n-ary combinations iterator - - Add methods PutBack::with_value and PutBack::into_parts. - -- 0.4.6 - - - Add method .sorted() - - Add module ``itertools::free`` with free function variants of common - iterator adaptors and methods. - For example ``enumerate(iterable)``, ``rev(iterable)``, and so on. - -- 0.4.5 - - - Add .flatten() - -- 0.4.4 - - - Allow composing ZipSlices with itself - -- 0.4.3 - - - Write iproduct!() as a single expression; this allows temporary values - in its arguments. - -- 0.4.2 - - - Add .fold_options() - - Require Rust 1.1 or later - -- 0.4.1 - - - Update .dropping() to take advantage of .nth() - -- 0.4.0 - - - .merge(), .unique() and .dedup() now perform better due to not using - function pointers - - Add free functions enumerate() and rev() - - Breaking changes: - - - Return types of .merge() and .merge_by() renamed and changed - - Method Merge::new removed - - .merge_by() now takes a closure that returns bool. - - Return type of .dedup() changed - - Return type of .mend_slices() changed - - Return type of .unique() changed - - Removed function times(), struct Times: use a range instead - - Removed deprecated macro icompr!() - - Removed deprecated FnMap and method .fn_map(): use .map_fn() - - .interleave_shortest() is no longer guaranteed to act like fused - -- 0.3.25 - - - Rename .sort_by() to .sorted_by(). Old name is deprecated. - - Fix well-formedness warnings from RFC 1214, no user visible impact - -- 0.3.24 - - - Improve performance of .merge()'s ordering function slightly - -- 0.3.23 - - - Added .chunks(), similar to (and based on) .group_by_lazy(). - - Tweak linspace to match numpy.linspace and make it double ended. - -- 0.3.22 - - - Added ZipSlices, a fast zip for slices - -- 0.3.21 - - - Remove `Debug` impl for `Format`, it will have different use later - -- 0.3.20 - - - Optimize .group_by_lazy() - -- 0.3.19 - - - Added .group_by_lazy(), a possibly nonallocating group by - - Added .format(), a nonallocating formatting helper for iterators - - Remove uses of RandomAccessIterator since it has been deprecated in rust. - -- 0.3.17 - - - Added (adopted) Unfold from rust - -- 0.3.16 - - - Added adaptors .unique(), .unique_by() - -- 0.3.15 - - - Added method .sort_by() - -- 0.3.14 - - - Added adaptor .while_some() - -- 0.3.13 - - - Added adaptor .interleave_shortest() - - Added adaptor .pad_using() - -- 0.3.11 - - - Added assert_equal function - -- 0.3.10 - - - Bugfix .combinations() size_hint. - -- 0.3.8 - - - Added source RepeatCall - -- 0.3.7 - - - Added adaptor PutBackN - - Added adaptor .combinations() - -- 0.3.6 - - - Added itertools::partition, partition a sequence in place based on a predicate. - - Deprecate icompr!() with no replacement. - -- 0.3.5 - - - .map_fn() replaces deprecated .fn_map(). - -- 0.3.4 - - - .take_while_ref() *by-ref adaptor* - - .coalesce() *adaptor* - - .mend_slices() *adaptor* - -- 0.3.3 - - - .dropping_back() *method* - - .fold1() *method* - - .is_empty_hint() *method* - -License -------- - -Dual-licensed to be compatible with the Rust project. - -Licensed under the Apache License, Version 2.0 -http://www.apache.org/licenses/LICENSE-2.0 or the MIT license -http://opensource.org/licenses/MIT, at your -option. This file may not be copied, modified, or distributed -except according to those terms. diff --git a/vendor/itertools-0.7.8/benches/bench1.rs b/vendor/itertools-0.7.8/benches/bench1.rs deleted file mode 100644 index d4342f93f2..0000000000 --- a/vendor/itertools-0.7.8/benches/bench1.rs +++ /dev/null @@ -1,735 +0,0 @@ -#![feature(test)] - -extern crate test; -#[macro_use] extern crate itertools; - -use test::{black_box}; -use itertools::Itertools; - -use itertools::free::cloned; - -use std::iter::repeat; -use std::cmp; -use std::ops::Add; - -mod extra; - -use extra::ZipSlices; - -#[bench] -fn slice_iter(b: &mut test::Bencher) -{ - let xs: Vec<_> = repeat(1i32).take(20).collect(); - b.iter(|| for elt in xs.iter() { - test::black_box(elt); - }) -} - -#[bench] -fn slice_iter_rev(b: &mut test::Bencher) -{ - let xs: Vec<_> = repeat(1i32).take(20).collect(); - b.iter(|| for elt in xs.iter().rev() { - test::black_box(elt); - }) -} - -#[bench] -fn zip_default_zip(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - for (&x, &y) in xs.iter().zip(&ys) { - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipdot_i32_default_zip(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0; - for (&x, &y) in xs.iter().zip(&ys) { - s += x * y; - } - s - }) -} - -#[bench] -fn zipdot_f32_default_zip(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0.; - for (&x, &y) in xs.iter().zip(&ys) { - s += x * y; - } - s - }) -} - -#[bench] -fn zip_default_zip3(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let zs = vec![0; 766]; - let xs = black_box(xs); - let ys = black_box(ys); - let zs = black_box(zs); - - b.iter(|| { - for ((&x, &y), &z) in xs.iter().zip(&ys).zip(&zs) { - test::black_box(x); - test::black_box(y); - test::black_box(z); - } - }) -} - -/* -#[bench] -fn zip_slices_ziptuple(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - - b.iter(|| { - let xs = black_box(&xs); - let ys = black_box(&ys); - for (&x, &y) in Zip::new((xs, ys)) { - test::black_box(x); - test::black_box(y); - } - }) -} -*/ - -#[bench] -fn zipslices(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - for (&x, &y) in ZipSlices::new(&xs, &ys) { - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipslices_mut(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let mut ys = black_box(ys); - - b.iter(|| { - for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipdot_i32_zipslices(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0i32; - for (&x, &y) in ZipSlices::new(&xs, &ys) { - s += x * y; - } - s - }) -} - -#[bench] -fn zipdot_f32_zipslices(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0.; - for (&x, &y) in ZipSlices::new(&xs, &ys) { - s += x * y; - } - s - }) -} - - -#[bench] -fn zip_checked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let xs = &xs[..len]; - let ys = &ys[..len]; - - for i in 0..len { - let x = xs[i]; - let y = ys[i]; - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipdot_i32_checked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let xs = &xs[..len]; - let ys = &ys[..len]; - - let mut s = 0i32; - - for i in 0..len { - s += xs[i] * ys[i]; - } - s - }) -} - -#[bench] -fn zipdot_f32_checked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let xs = &xs[..len]; - let ys = &ys[..len]; - - let mut s = 0.; - - for i in 0..len { - s += xs[i] * ys[i]; - } - s - }) -} - -#[bench] -fn zipdot_f32_checked_counted_unrolled_loop(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let mut xs = &xs[..len]; - let mut ys = &ys[..len]; - - let mut s = 0.; - let (mut p0, mut p1, mut p2, mut p3, mut p4, mut p5, mut p6, mut p7) = - (0., 0., 0., 0., 0., 0., 0., 0.); - - // how to unroll and have bounds checks eliminated (by cristicbz) - // split sum into eight parts to enable vectorization (by bluss) - while xs.len() >= 8 { - p0 += xs[0] * ys[0]; - p1 += xs[1] * ys[1]; - p2 += xs[2] * ys[2]; - p3 += xs[3] * ys[3]; - p4 += xs[4] * ys[4]; - p5 += xs[5] * ys[5]; - p6 += xs[6] * ys[6]; - p7 += xs[7] * ys[7]; - - xs = &xs[8..]; - ys = &ys[8..]; - } - s += p0 + p4; - s += p1 + p5; - s += p2 + p6; - s += p3 + p7; - - for i in 0..xs.len() { - s += xs[i] * ys[i]; - } - s - }) -} - -#[bench] -fn zip_unchecked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let len = cmp::min(xs.len(), ys.len()); - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - test::black_box(x); - test::black_box(y); - } - } - }) -} - -#[bench] -fn zipdot_i32_unchecked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let len = cmp::min(xs.len(), ys.len()); - let mut s = 0i32; - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - s += x * y; - } - } - s - }) -} - -#[bench] -fn zipdot_f32_unchecked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2.; 1024]; - let ys = vec![2.; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let len = cmp::min(xs.len(), ys.len()); - let mut s = 0f32; - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - s += x * y; - } - } - s - }) -} - -#[bench] -fn zip_unchecked_counted_loop3(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let zs = vec![0; 766]; - let xs = black_box(xs); - let ys = black_box(ys); - let zs = black_box(zs); - - b.iter(|| { - let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len())); - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - let z = *zs.get_unchecked(i); - test::black_box(x); - test::black_box(y); - test::black_box(z); - } - } - }) -} - -#[bench] -fn group_by_lazy_1(b: &mut test::Bencher) { - let mut data = vec![0; 1024]; - for (index, elt) in data.iter_mut().enumerate() { - *elt = index / 10; - } - - let data = test::black_box(data); - - b.iter(|| { - for (_key, group) in &data.iter().group_by(|elt| **elt) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn group_by_lazy_2(b: &mut test::Bencher) { - let mut data = vec![0; 1024]; - for (index, elt) in data.iter_mut().enumerate() { - *elt = index / 2; - } - - let data = test::black_box(data); - - b.iter(|| { - for (_key, group) in &data.iter().group_by(|elt| **elt) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn slice_chunks(b: &mut test::Bencher) { - let data = vec![0; 1024]; - - let data = test::black_box(data); - let sz = test::black_box(10); - - b.iter(|| { - for group in data.chunks(sz) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn chunks_lazy_1(b: &mut test::Bencher) { - let data = vec![0; 1024]; - - let data = test::black_box(data); - let sz = test::black_box(10); - - b.iter(|| { - for group in &data.iter().chunks(sz) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn equal(b: &mut test::Bencher) { - let data = vec![7; 1024]; - let l = data.len(); - let alpha = test::black_box(&data[1..]); - let beta = test::black_box(&data[..l - 1]); - b.iter(|| { - itertools::equal(alpha, beta) - }) -} - -#[bench] -fn merge_default(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - b.iter(|| { - data1.iter().merge(&data2).count() - }) -} - -#[bench] -fn merge_by_cmp(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - b.iter(|| { - data1.iter().merge_by(&data2, PartialOrd::le).count() - }) -} - -#[bench] -fn merge_by_lt(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - b.iter(|| { - data1.iter().merge_by(&data2, |a, b| a <= b).count() - }) -} - -#[bench] -fn kmerge_default(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - let its = &[data1.iter(), data2.iter()]; - b.iter(|| { - its.iter().cloned().kmerge().count() - }) -} - -#[bench] -fn kmerge_tenway(b: &mut test::Bencher) { - let mut data = vec![0; 10240]; - - let mut state = 1729u16; - fn rng(state: &mut u16) -> u16 { - let new = state.wrapping_mul(31421) + 6927; - *state = new; - new - } - - for elt in &mut data { - *elt = rng(&mut state); - } - - let mut chunks = Vec::new(); - let mut rest = &mut data[..]; - while rest.len() > 0 { - let chunk_len = 1 + rng(&mut state) % 512; - let chunk_len = cmp::min(rest.len(), chunk_len as usize); - let (fst, tail) = {rest}.split_at_mut(chunk_len); - fst.sort(); - chunks.push(fst.iter().cloned()); - rest = tail; - } - - // println!("Chunk lengths: {}", chunks.iter().format_with(", ", |elt, f| f(&elt.len()))); - - b.iter(|| { - chunks.iter().cloned().kmerge().count() - }) -} - - -fn fast_integer_sum<I>(iter: I) -> I::Item - where I: IntoIterator, - I::Item: Default + Add<Output=I::Item> -{ - iter.into_iter().fold(<_>::default(), |x, y| x + y) -} - - -#[bench] -fn step_vec_2(b: &mut test::Bencher) { - let v = vec![0; 1024]; - b.iter(|| { - fast_integer_sum(cloned(v.iter().step(2))) - }); -} - -#[bench] -fn step_vec_10(b: &mut test::Bencher) { - let v = vec![0; 1024]; - b.iter(|| { - fast_integer_sum(cloned(v.iter().step(10))) - }); -} - -#[bench] -fn step_range_2(b: &mut test::Bencher) { - let v = black_box(0..1024); - b.iter(|| { - fast_integer_sum(v.clone().step(2)) - }); -} - -#[bench] -fn step_range_10(b: &mut test::Bencher) { - let v = black_box(0..1024); - b.iter(|| { - fast_integer_sum(v.clone().step(10)) - }); -} - -#[bench] -fn cartesian_product_iterator(b: &mut test::Bencher) -{ - let xs = vec![0; 16]; - - b.iter(|| { - let mut sum = 0; - for (&x, &y, &z) in iproduct!(&xs, &xs, &xs) { - sum += x; - sum += y; - sum += z; - } - sum - }) -} - -#[bench] -fn cartesian_product_fold(b: &mut test::Bencher) -{ - let xs = vec![0; 16]; - - b.iter(|| { - let mut sum = 0; - iproduct!(&xs, &xs, &xs).fold((), |(), (&x, &y, &z)| { - sum += x; - sum += y; - sum += z; - }); - sum - }) -} - -#[bench] -fn multi_cartesian_product_iterator(b: &mut test::Bencher) -{ - let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; - - b.iter(|| { - let mut sum = 0; - for x in xs.into_iter().multi_cartesian_product() { - sum += x[0]; - sum += x[1]; - sum += x[2]; - } - sum - }) -} - -#[bench] -fn multi_cartesian_product_fold(b: &mut test::Bencher) -{ - let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; - - b.iter(|| { - let mut sum = 0; - xs.into_iter().multi_cartesian_product().fold((), |(), x| { - sum += x[0]; - sum += x[1]; - sum += x[2]; - }); - sum - }) -} - -#[bench] -fn cartesian_product_nested_for(b: &mut test::Bencher) -{ - let xs = vec![0; 16]; - - b.iter(|| { - let mut sum = 0; - for &x in &xs { - for &y in &xs { - for &z in &xs { - sum += x; - sum += y; - sum += z; - } - } - } - sum - }) -} diff --git a/vendor/itertools-0.7.8/benches/extra/mod.rs b/vendor/itertools-0.7.8/benches/extra/mod.rs deleted file mode 100644 index 5ddb5772f4..0000000000 --- a/vendor/itertools-0.7.8/benches/extra/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ - - -pub use self::zipslices::ZipSlices; -mod zipslices; diff --git a/vendor/itertools-0.7.8/benches/extra/zipslices.rs b/vendor/itertools-0.7.8/benches/extra/zipslices.rs deleted file mode 100644 index 493a539fd6..0000000000 --- a/vendor/itertools-0.7.8/benches/extra/zipslices.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::cmp; - -// Note: There are different ways to implement ZipSlices. -// This version performed the best in benchmarks. -// -// I also implemented a version with three pointes (tptr, tend, uptr), -// that mimiced slice::Iter and only checked bounds by using tptr == tend, -// but that was inferior to this solution. - -/// An iterator which iterates two slices simultaneously. -/// -/// `ZipSlices` acts like a double-ended `.zip()` iterator. -/// -/// It was intended to be more efficient than `.zip()`, and it was, then -/// rustc changed how it optimizes so it can not promise improved performance -/// at this time. -/// -/// Note that elements past the end of the shortest of the two slices are ignored. -/// -/// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example, -/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`. -#[derive(Clone)] -pub struct ZipSlices<T, U> { - t: T, - u: U, - len: usize, - index: usize, -} - -impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> { - /// Create a new `ZipSlices` from slices `a` and `b`. - /// - /// Act like a double-ended `.zip()` iterator, but more efficiently. - /// - /// Note that elements past the end of the shortest of the two slices are ignored. - #[inline(always)] - pub fn new(a: &'a [A], b: &'b [B]) -> Self { - let minl = cmp::min(a.len(), b.len()); - ZipSlices { - t: a, - u: b, - len: minl, - index: 0, - } - } -} - -impl<T, U> ZipSlices<T, U> - where T: Slice, - U: Slice -{ - /// Create a new `ZipSlices` from slices `a` and `b`. - /// - /// Act like a double-ended `.zip()` iterator, but more efficiently. - /// - /// Note that elements past the end of the shortest of the two slices are ignored. - #[inline(always)] - pub fn from_slices(a: T, b: U) -> Self { - let minl = cmp::min(a.len(), b.len()); - ZipSlices { - t: a, - u: b, - len: minl, - index: 0, - } - } -} - -impl<T, U> Iterator for ZipSlices<T, U> - where T: Slice, - U: Slice -{ - type Item = (T::Item, U::Item); - - #[inline(always)] - fn next(&mut self) -> Option<Self::Item> { - unsafe { - if self.index >= self.len { - None - } else { - let i = self.index; - self.index += 1; - Some(( - self.t.get_unchecked(i), - self.u.get_unchecked(i))) - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let len = self.len - self.index; - (len, Some(len)) - } -} - -impl<T, U> DoubleEndedIterator for ZipSlices<T, U> - where T: Slice, - U: Slice -{ - #[inline(always)] - fn next_back(&mut self) -> Option<Self::Item> { - unsafe { - if self.index >= self.len { - None - } else { - self.len -= 1; - let i = self.len; - Some(( - self.t.get_unchecked(i), - self.u.get_unchecked(i))) - } - } - } -} - -impl<T, U> ExactSizeIterator for ZipSlices<T, U> - where T: Slice, - U: Slice -{} - -unsafe impl<T, U> Slice for ZipSlices<T, U> - where T: Slice, - U: Slice -{ - type Item = (T::Item, U::Item); - - fn len(&self) -> usize { - self.len - self.index - } - - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - (self.t.get_unchecked(i), - self.u.get_unchecked(i)) - } -} - -/// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`. -/// -/// Unsafe trait because: -/// -/// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`. -pub unsafe trait Slice { - /// The type of a reference to the slice's elements - type Item; - #[doc(hidden)] - fn len(&self) -> usize; - #[doc(hidden)] - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; -} - -unsafe impl<'a, T> Slice for &'a [T] { - type Item = &'a T; - #[inline(always)] - fn len(&self) -> usize { (**self).len() } - #[inline(always)] - unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { - debug_assert!(i < self.len()); - (**self).get_unchecked(i) - } -} - -unsafe impl<'a, T> Slice for &'a mut [T] { - type Item = &'a mut T; - #[inline(always)] - fn len(&self) -> usize { (**self).len() } - #[inline(always)] - unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { - debug_assert!(i < self.len()); - // override the lifetime constraints of &mut &'a mut [T] - (*(*self as *mut [T])).get_unchecked_mut(i) - } -} - -#[test] -fn zipslices() { - - let xs = [1, 2, 3, 4, 5, 6]; - let ys = [1, 2, 3, 7]; - ::itertools::assert_equal(ZipSlices::new(&xs, &ys), xs.iter().zip(&ys)); - - let xs = [1, 2, 3, 4, 5, 6]; - let mut ys = [0; 6]; - for (x, y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { - *y = *x; - } - ::itertools::assert_equal(&xs, &ys); -} - diff --git a/vendor/itertools-0.7.8/benches/tree_fold1.rs b/vendor/itertools-0.7.8/benches/tree_fold1.rs deleted file mode 100644 index b71589f3fe..0000000000 --- a/vendor/itertools-0.7.8/benches/tree_fold1.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate itertools; - -use itertools::Itertools; -use itertools::cloned; -use test::Bencher; - -trait IterEx : Iterator { - // Another efficient implementation against which to compare, - // but needs `std` so is less desirable. - fn tree_fold1_vec<F>(self, mut f: F) -> Option<Self::Item> - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, - { - let hint = self.size_hint().0; - let cap = std::mem::size_of::<usize>() * 8 - hint.leading_zeros() as usize; - let mut stack = Vec::with_capacity(cap); - self.enumerate().foreach(|(mut i, mut x)| { - while (i & 1) != 0 { - x = f(stack.pop().unwrap(), x); - i >>= 1; - } - stack.push(x); - }); - stack.into_iter().fold1(f) - } -} -impl<T:Iterator> IterEx for T {} - -macro_rules! def_benchs { - ($N:expr, - $FUN:ident, - $BENCH_NAME:ident, - ) => ( - mod $BENCH_NAME { - use super::*; - - #[bench] - fn sum(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N).collect(); - b.iter(|| { - cloned(&v).$FUN(|x, y| x + y) - }); - } - - #[bench] - fn complex_iter(b: &mut Bencher) { - let u = (3..).take($N / 2); - let v = (5..).take($N / 2); - let it = u.chain(v); - - b.iter(|| { - it.clone().map(|x| x as f32).$FUN(f32::atan2) - }); - } - - #[bench] - fn string_format(b: &mut Bencher) { - // This goes quadratic with linear `fold1`, so use a smaller - // size to not waste too much time in travis. The allocations - // in here are so expensive anyway that it'll still take - // way longer per iteration than the other two benchmarks. - let v: Vec<u32> = (0.. ($N/4)).collect(); - b.iter(|| { - cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y)) - }); - } - } - ) -} - -def_benchs!{ - 10_000, - fold1, - fold1_10k, -} - -def_benchs!{ - 10_000, - tree_fold1, - tree_fold1_stack_10k, -} - -def_benchs!{ - 10_000, - tree_fold1_vec, - tree_fold1_vec_10k, -} - -def_benchs!{ - 100, - fold1, - fold1_100, -} - -def_benchs!{ - 100, - tree_fold1, - tree_fold1_stack_100, -} - -def_benchs!{ - 100, - tree_fold1_vec, - tree_fold1_vec_100, -} - -def_benchs!{ - 8, - fold1, - fold1_08, -} - -def_benchs!{ - 8, - tree_fold1, - tree_fold1_stack_08, -} - -def_benchs!{ - 8, - tree_fold1_vec, - tree_fold1_vec_08, -} diff --git a/vendor/itertools-0.7.8/benches/tuple_combinations.rs b/vendor/itertools-0.7.8/benches/tuple_combinations.rs deleted file mode 100644 index 1f9075dad3..0000000000 --- a/vendor/itertools-0.7.8/benches/tuple_combinations.rs +++ /dev/null @@ -1,97 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate itertools; - -use test::{black_box, Bencher}; -use itertools::Itertools; - -// aproximate 100_000 iterations for each combination -const N1: usize = 100_000; -const N2: usize = 448; -const N3: usize = 86; -const N4: usize = 41; - -#[bench] -fn comb_for1(b: &mut Bencher) { - b.iter(|| { - for i in 0..N1 { - black_box(i); - } - }); -} - -#[bench] -fn comb_for2(b: &mut Bencher) { - b.iter(|| { - for i in 0..N2 { - for j in (i + 1)..N2 { - black_box(i + j); - } - } - }); -} - -#[bench] -fn comb_for3(b: &mut Bencher) { - b.iter(|| { - for i in 0..N3 { - for j in (i + 1)..N3 { - for k in (j + 1)..N3 { - black_box(i + j + k); - } - } - } - }); -} - -#[bench] -fn comb_for4(b: &mut Bencher) { - b.iter(|| { - for i in 0..N4 { - for j in (i + 1)..N4 { - for k in (j + 1)..N4 { - for l in (k + 1)..N4 { - black_box(i + j + k + l); - } - } - } - } - }); -} - -#[bench] -fn comb_c1(b: &mut Bencher) { - b.iter(|| { - for (i,) in (0..N1).tuple_combinations() { - black_box(i); - } - }); -} - -#[bench] -fn comb_c2(b: &mut Bencher) { - b.iter(|| { - for (i, j) in (0..N2).tuple_combinations() { - black_box(i + j); - } - }); -} - -#[bench] -fn comb_c3(b: &mut Bencher) { - b.iter(|| { - for (i, j, k) in (0..N3).tuple_combinations() { - black_box(i + j + k); - } - }); -} - -#[bench] -fn comb_c4(b: &mut Bencher) { - b.iter(|| { - for (i, j, k, l) in (0..N4).tuple_combinations() { - black_box(i + j + k + l); - } - }); -} diff --git a/vendor/itertools-0.7.8/benches/tuples.rs b/vendor/itertools-0.7.8/benches/tuples.rs deleted file mode 100644 index b0f2990fdf..0000000000 --- a/vendor/itertools-0.7.8/benches/tuples.rs +++ /dev/null @@ -1,190 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate itertools; - -use test::Bencher; -use itertools::Itertools; - -fn s1(a: u32) -> u32 { - a -} - -fn s2(a: u32, b: u32) -> u32 { - a + b -} - -fn s3(a: u32, b: u32, c: u32) -> u32 { - a + b + c -} - -fn s4(a: u32, b: u32, c: u32, d: u32) -> u32 { - a + b + c + d -} - -fn sum_s1(s: &[u32]) -> u32 { - s1(s[0]) -} - -fn sum_s2(s: &[u32]) -> u32 { - s2(s[0], s[1]) -} - -fn sum_s3(s: &[u32]) -> u32 { - s3(s[0], s[1], s[2]) -} - -fn sum_s4(s: &[u32]) -> u32 { - s4(s[0], s[1], s[2], s[3]) -} - -fn sum_t1(s: &(&u32, )) -> u32 { - s1(*s.0) -} - -fn sum_t2(s: &(&u32, &u32)) -> u32 { - s2(*s.0, *s.1) -} - -fn sum_t3(s: &(&u32, &u32, &u32)) -> u32 { - s3(*s.0, *s.1, *s.2) -} - -fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 { - s4(*s.0, *s.1, *s.2, *s.3) -} - -macro_rules! def_benchs { - ($N:expr; - $TUPLE_FUN:ident, - $TUPLES:ident, - $TUPLE_WINDOWS:ident; - $SLICE_FUN:ident, - $CHUNKS:ident, - $WINDOWS:ident; - $FOR_CHUNKS:ident, - $FOR_WINDOWS:ident - ) => ( - #[bench] - fn $FOR_CHUNKS(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N * 1_000).collect(); - let mut s = 0; - b.iter(|| { - let mut j = 0; - for _ in 0..1_000 { - s += $SLICE_FUN(&v[j..(j + $N)]); - j += $N; - } - s - }); - } - - #[bench] - fn $FOR_WINDOWS(b: &mut Bencher) { - let v: Vec<u32> = (0..1_000).collect(); - let mut s = 0; - b.iter(|| { - for i in 0..(1_000 - $N) { - s += $SLICE_FUN(&v[i..(i + $N)]); - } - s - }); - } - - #[bench] - fn $TUPLES(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N * 1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.iter().tuples() { - s += $TUPLE_FUN(&x); - } - s - }); - } - - #[bench] - fn $CHUNKS(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N * 1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.chunks($N) { - s += $SLICE_FUN(x); - } - s - }); - } - - #[bench] - fn $TUPLE_WINDOWS(b: &mut Bencher) { - let v: Vec<u32> = (0..1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.iter().tuple_windows() { - s += $TUPLE_FUN(&x); - } - s - }); - } - - #[bench] - fn $WINDOWS(b: &mut Bencher) { - let v: Vec<u32> = (0..1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.windows($N) { - s += $SLICE_FUN(x); - } - s - }); - } - ) -} - -def_benchs!{ - 1; - sum_t1, - tuple_chunks_1, - tuple_windows_1; - sum_s1, - slice_chunks_1, - slice_windows_1; - for_chunks_1, - for_windows_1 -} - -def_benchs!{ - 2; - sum_t2, - tuple_chunks_2, - tuple_windows_2; - sum_s2, - slice_chunks_2, - slice_windows_2; - for_chunks_2, - for_windows_2 -} - -def_benchs!{ - 3; - sum_t3, - tuple_chunks_3, - tuple_windows_3; - sum_s3, - slice_chunks_3, - slice_windows_3; - for_chunks_3, - for_windows_3 -} - -def_benchs!{ - 4; - sum_t4, - tuple_chunks_4, - tuple_windows_4; - sum_s4, - slice_chunks_4, - slice_windows_4; - for_chunks_4, - for_windows_4 -} diff --git a/vendor/itertools-0.7.8/bors.toml b/vendor/itertools-0.7.8/bors.toml deleted file mode 100644 index 2523b2d82f..0000000000 --- a/vendor/itertools-0.7.8/bors.toml +++ /dev/null @@ -1,3 +0,0 @@ -status = [ -"continuous-integration/travis-ci/push" -] diff --git a/vendor/itertools-0.7.8/custom.css b/vendor/itertools-0.7.8/custom.css deleted file mode 100644 index bd4b11e92e..0000000000 --- a/vendor/itertools-0.7.8/custom.css +++ /dev/null @@ -1,29 +0,0 @@ - -.docblock pre.rust { background: #eeeeff; } -pre.trait, pre.fn, pre.struct, pre.enum, pre.typedef { background: #fcfefc; } - -/* Small “example” label for doc examples */ -.docblock pre.rust::before { - content: "example"; - float: right; - font-style: italic; - font-size: 0.8em; - margin-top: -10px; - margin-right: -5px; -} - - -/* Fixup where display in trait listing */ -pre.trait .where::before { -content: '\a '; -} - -.docblock code { - background-color: inherit; - font-weight: bold; - padding: 0 0.1em; -} - -a.test-arrow { - display: none; -} diff --git a/vendor/itertools-0.7.8/examples/iris.data b/vendor/itertools-0.7.8/examples/iris.data deleted file mode 100644 index a3490e0e07..0000000000 --- a/vendor/itertools-0.7.8/examples/iris.data +++ /dev/null @@ -1,150 +0,0 @@ -5.1,3.5,1.4,0.2,Iris-setosa -4.9,3.0,1.4,0.2,Iris-setosa -4.7,3.2,1.3,0.2,Iris-setosa -4.6,3.1,1.5,0.2,Iris-setosa -5.0,3.6,1.4,0.2,Iris-setosa -5.4,3.9,1.7,0.4,Iris-setosa -4.6,3.4,1.4,0.3,Iris-setosa -5.0,3.4,1.5,0.2,Iris-setosa -4.4,2.9,1.4,0.2,Iris-setosa -4.9,3.1,1.5,0.1,Iris-setosa -5.4,3.7,1.5,0.2,Iris-setosa -4.8,3.4,1.6,0.2,Iris-setosa -4.8,3.0,1.4,0.1,Iris-setosa -4.3,3.0,1.1,0.1,Iris-setosa -5.8,4.0,1.2,0.2,Iris-setosa -5.7,4.4,1.5,0.4,Iris-setosa -5.4,3.9,1.3,0.4,Iris-setosa -5.1,3.5,1.4,0.3,Iris-setosa -5.7,3.8,1.7,0.3,Iris-setosa -5.1,3.8,1.5,0.3,Iris-setosa -5.4,3.4,1.7,0.2,Iris-setosa -5.1,3.7,1.5,0.4,Iris-setosa -4.6,3.6,1.0,0.2,Iris-setosa -5.1,3.3,1.7,0.5,Iris-setosa -4.8,3.4,1.9,0.2,Iris-setosa -5.0,3.0,1.6,0.2,Iris-setosa -5.0,3.4,1.6,0.4,Iris-setosa -5.2,3.5,1.5,0.2,Iris-setosa -5.2,3.4,1.4,0.2,Iris-setosa -4.7,3.2,1.6,0.2,Iris-setosa -4.8,3.1,1.6,0.2,Iris-setosa -5.4,3.4,1.5,0.4,Iris-setosa -5.2,4.1,1.5,0.1,Iris-setosa -5.5,4.2,1.4,0.2,Iris-setosa -4.9,3.1,1.5,0.1,Iris-setosa -5.0,3.2,1.2,0.2,Iris-setosa -5.5,3.5,1.3,0.2,Iris-setosa -4.9,3.1,1.5,0.1,Iris-setosa -4.4,3.0,1.3,0.2,Iris-setosa -5.1,3.4,1.5,0.2,Iris-setosa -5.0,3.5,1.3,0.3,Iris-setosa -4.5,2.3,1.3,0.3,Iris-setosa -4.4,3.2,1.3,0.2,Iris-setosa -5.0,3.5,1.6,0.6,Iris-setosa -5.1,3.8,1.9,0.4,Iris-setosa -4.8,3.0,1.4,0.3,Iris-setosa -5.1,3.8,1.6,0.2,Iris-setosa -4.6,3.2,1.4,0.2,Iris-setosa -5.3,3.7,1.5,0.2,Iris-setosa -5.0,3.3,1.4,0.2,Iris-setosa -7.0,3.2,4.7,1.4,Iris-versicolor -6.4,3.2,4.5,1.5,Iris-versicolor -6.9,3.1,4.9,1.5,Iris-versicolor -5.5,2.3,4.0,1.3,Iris-versicolor -6.5,2.8,4.6,1.5,Iris-versicolor -5.7,2.8,4.5,1.3,Iris-versicolor -6.3,3.3,4.7,1.6,Iris-versicolor -4.9,2.4,3.3,1.0,Iris-versicolor -6.6,2.9,4.6,1.3,Iris-versicolor -5.2,2.7,3.9,1.4,Iris-versicolor -5.0,2.0,3.5,1.0,Iris-versicolor -5.9,3.0,4.2,1.5,Iris-versicolor -6.0,2.2,4.0,1.0,Iris-versicolor -6.1,2.9,4.7,1.4,Iris-versicolor -5.6,2.9,3.6,1.3,Iris-versicolor -6.7,3.1,4.4,1.4,Iris-versicolor -5.6,3.0,4.5,1.5,Iris-versicolor -5.8,2.7,4.1,1.0,Iris-versicolor -6.2,2.2,4.5,1.5,Iris-versicolor -5.6,2.5,3.9,1.1,Iris-versicolor -5.9,3.2,4.8,1.8,Iris-versicolor -6.1,2.8,4.0,1.3,Iris-versicolor -6.3,2.5,4.9,1.5,Iris-versicolor -6.1,2.8,4.7,1.2,Iris-versicolor -6.4,2.9,4.3,1.3,Iris-versicolor -6.6,3.0,4.4,1.4,Iris-versicolor -6.8,2.8,4.8,1.4,Iris-versicolor -6.7,3.0,5.0,1.7,Iris-versicolor -6.0,2.9,4.5,1.5,Iris-versicolor -5.7,2.6,3.5,1.0,Iris-versicolor -5.5,2.4,3.8,1.1,Iris-versicolor -5.5,2.4,3.7,1.0,Iris-versicolor -5.8,2.7,3.9,1.2,Iris-versicolor -6.0,2.7,5.1,1.6,Iris-versicolor -5.4,3.0,4.5,1.5,Iris-versicolor -6.0,3.4,4.5,1.6,Iris-versicolor -6.7,3.1,4.7,1.5,Iris-versicolor -6.3,2.3,4.4,1.3,Iris-versicolor -5.6,3.0,4.1,1.3,Iris-versicolor -5.5,2.5,4.0,1.3,Iris-versicolor -5.5,2.6,4.4,1.2,Iris-versicolor -6.1,3.0,4.6,1.4,Iris-versicolor -5.8,2.6,4.0,1.2,Iris-versicolor -5.0,2.3,3.3,1.0,Iris-versicolor -5.6,2.7,4.2,1.3,Iris-versicolor -5.7,3.0,4.2,1.2,Iris-versicolor -5.7,2.9,4.2,1.3,Iris-versicolor -6.2,2.9,4.3,1.3,Iris-versicolor -5.1,2.5,3.0,1.1,Iris-versicolor -5.7,2.8,4.1,1.3,Iris-versicolor -6.3,3.3,6.0,2.5,Iris-virginica -5.8,2.7,5.1,1.9,Iris-virginica -7.1,3.0,5.9,2.1,Iris-virginica -6.3,2.9,5.6,1.8,Iris-virginica -6.5,3.0,5.8,2.2,Iris-virginica -7.6,3.0,6.6,2.1,Iris-virginica -4.9,2.5,4.5,1.7,Iris-virginica -7.3,2.9,6.3,1.8,Iris-virginica -6.7,2.5,5.8,1.8,Iris-virginica -7.2,3.6,6.1,2.5,Iris-virginica -6.5,3.2,5.1,2.0,Iris-virginica -6.4,2.7,5.3,1.9,Iris-virginica -6.8,3.0,5.5,2.1,Iris-virginica -5.7,2.5,5.0,2.0,Iris-virginica -5.8,2.8,5.1,2.4,Iris-virginica -6.4,3.2,5.3,2.3,Iris-virginica -6.5,3.0,5.5,1.8,Iris-virginica -7.7,3.8,6.7,2.2,Iris-virginica -7.7,2.6,6.9,2.3,Iris-virginica -6.0,2.2,5.0,1.5,Iris-virginica -6.9,3.2,5.7,2.3,Iris-virginica -5.6,2.8,4.9,2.0,Iris-virginica -7.7,2.8,6.7,2.0,Iris-virginica -6.3,2.7,4.9,1.8,Iris-virginica -6.7,3.3,5.7,2.1,Iris-virginica -7.2,3.2,6.0,1.8,Iris-virginica -6.2,2.8,4.8,1.8,Iris-virginica -6.1,3.0,4.9,1.8,Iris-virginica -6.4,2.8,5.6,2.1,Iris-virginica -7.2,3.0,5.8,1.6,Iris-virginica -7.4,2.8,6.1,1.9,Iris-virginica -7.9,3.8,6.4,2.0,Iris-virginica -6.4,2.8,5.6,2.2,Iris-virginica -6.3,2.8,5.1,1.5,Iris-virginica -6.1,2.6,5.6,1.4,Iris-virginica -7.7,3.0,6.1,2.3,Iris-virginica -6.3,3.4,5.6,2.4,Iris-virginica -6.4,3.1,5.5,1.8,Iris-virginica -6.0,3.0,4.8,1.8,Iris-virginica -6.9,3.1,5.4,2.1,Iris-virginica -6.7,3.1,5.6,2.4,Iris-virginica -6.9,3.1,5.1,2.3,Iris-virginica -5.8,2.7,5.1,1.9,Iris-virginica -6.8,3.2,5.9,2.3,Iris-virginica -6.7,3.3,5.7,2.5,Iris-virginica -6.7,3.0,5.2,2.3,Iris-virginica -6.3,2.5,5.0,1.9,Iris-virginica -6.5,3.0,5.2,2.0,Iris-virginica -6.2,3.4,5.4,2.3,Iris-virginica -5.9,3.0,5.1,1.8,Iris-virginica diff --git a/vendor/itertools-0.7.8/examples/iris.rs b/vendor/itertools-0.7.8/examples/iris.rs deleted file mode 100644 index c09afbea0d..0000000000 --- a/vendor/itertools-0.7.8/examples/iris.rs +++ /dev/null @@ -1,141 +0,0 @@ -/// -/// This example parses, sorts and groups the iris dataset -/// and does some simple manipulations. -/// -/// Iterators and itertools functionality are used throughout. -/// -/// - -extern crate itertools; - -use itertools::Itertools; -use std::collections::HashMap; -use std::iter::repeat; -use std::num::ParseFloatError; -use std::str::FromStr; - -static DATA: &'static str = include_str!("iris.data"); - -#[derive(Clone, Debug)] -struct Iris { - name: String, - data: [f32; 4], -} - -#[derive(Clone, Debug)] -enum ParseError { - Numeric(ParseFloatError), - Other(&'static str), -} - -impl From<ParseFloatError> for ParseError { - fn from(err: ParseFloatError) -> Self { - ParseError::Numeric(err) - } -} - -/// Parse an Iris from a comma-separated line -impl FromStr for Iris { - type Err = ParseError; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - let mut iris = Iris { name: "".into(), data: [0.; 4] }; - let mut parts = s.split(",").map(str::trim); - - // using Iterator::by_ref() - for (index, part) in parts.by_ref().take(4).enumerate() { - iris.data[index] = try!(part.parse::<f32>()); - } - if let Some(name) = parts.next() { - iris.name = name.into(); - } else { - return Err(ParseError::Other("Missing name")) - } - Ok(iris) - } -} - -fn main() { - // using Itertools::fold_results to create the result of parsing - let irises = DATA.lines() - .map(str::parse) - .fold_results(Vec::new(), |mut v, iris: Iris| { - v.push(iris); - v - }); - let mut irises = match irises { - Err(e) => { - println!("Error parsing: {:?}", e); - std::process::exit(1); - } - Ok(data) => data, - }; - - // Sort them and group them - irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name)); - - // using Iterator::cycle() - let mut plot_symbols = "+ox".chars().cycle(); - let mut symbolmap = HashMap::new(); - - // using Itertools::group_by - for (species, species_group) in &irises.iter().group_by(|iris| &iris.name) { - // assign a plot symbol - symbolmap.entry(species).or_insert_with(|| { - plot_symbols.next().unwrap() - }); - println!("{} (symbol={})", species, symbolmap[species]); - - for iris in species_group { - // using Itertools::format for lazy formatting - println!("{:>3.1}", iris.data.iter().format(", ")); - } - - } - - // Look at all combinations of the four columns - // - // See https://en.wikipedia.org/wiki/Iris_flower_data_set - // - let n = 30; // plot size - let mut plot = vec![' '; n * n]; - - // using Itertools::tuple_combinations - for (a, b) in (0..4).tuple_combinations() { - println!("Column {} vs {}:", a, b); - - // Clear plot - // - // using std::iter::repeat; - // using Itertools::set_from - plot.iter_mut().set_from(repeat(' ')); - - // using Itertools::minmax - let min_max = |data: &[Iris], col| { - data.iter() - .map(|iris| iris.data[col]) - .minmax() - .into_option() - .expect("Can't find min/max of empty iterator") - }; - let (min_x, max_x) = min_max(&irises, a); - let (min_y, max_y) = min_max(&irises, b); - - // Plot the data points - let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize; - let flip = |ix| n - 1 - ix; // reverse axis direction - - for iris in &irises { - let ix = round_to_grid(iris.data[a], min_x, max_x); - let iy = flip(round_to_grid(iris.data[b], min_y, max_y)); - plot[n * iy + ix] = symbolmap[&iris.name]; - } - - // render plot - // - // using Itertools::join - for line in plot.chunks(n) { - println!("{}", line.iter().join(" ")) - } - } -} diff --git a/vendor/itertools-0.7.8/src/adaptors/mod.rs b/vendor/itertools-0.7.8/src/adaptors/mod.rs deleted file mode 100644 index 127edaa56c..0000000000 --- a/vendor/itertools-0.7.8/src/adaptors/mod.rs +++ /dev/null @@ -1,1293 +0,0 @@ -//! Licensed under the Apache License, Version 2.0 -//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license -//! http://opensource.org/licenses/MIT, at your -//! option. This file may not be copied, modified, or distributed -//! except according to those terms. - -mod multi_product; -#[cfg(feature = "use_std")] -pub use self::multi_product::*; - -use std::fmt; -use std::mem::replace; -use std::iter::{Fuse, Peekable, FromIterator}; -use std::marker::PhantomData; -use size_hint; -use fold; - -macro_rules! clone_fields { - ($name:ident, $base:expr, $($field:ident),+) => ( - $name { - $( - $field : $base . $field .clone() - ),* - } - ); -} - -/// An iterator adaptor that alternates elements from two iterators until both -/// run out. -/// -/// This iterator is *fused*. -/// -/// See [`.interleave()`](../trait.Itertools.html#method.interleave) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Interleave<I, J> { - a: Fuse<I>, - b: Fuse<J>, - flag: bool, -} - -/// Create an iterator that interleaves elements in `i` and `j`. -/// -/// `IntoIterator` enabled version of `i.interleave(j)`. -/// -/// ``` -/// use itertools::interleave; -/// -/// for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { -/// /* loop body */ -/// } -/// ``` -pub fn interleave<I, J>(i: I, j: J) -> Interleave<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> - where I: IntoIterator, - J: IntoIterator<Item = I::Item> -{ - Interleave { - a: i.into_iter().fuse(), - b: j.into_iter().fuse(), - flag: false, - } -} - -impl<I, J> Iterator for Interleave<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - self.flag = !self.flag; - if self.flag { - match self.a.next() { - None => self.b.next(), - r => r, - } - } else { - match self.b.next() { - None => self.a.next(), - r => r, - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add(self.a.size_hint(), self.b.size_hint()) - } -} - -/// An iterator adaptor that alternates elements from the two iterators until -/// one of them runs out. -/// -/// This iterator is *fused*. -/// -/// See [`.interleave_shortest()`](../trait.Itertools.html#method.interleave_shortest) -/// for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct InterleaveShortest<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - it0: I, - it1: J, - phase: bool, // false ==> it0, true ==> it1 -} - -/// Create a new `InterleaveShortest` iterator. -pub fn interleave_shortest<I, J>(a: I, b: J) -> InterleaveShortest<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - InterleaveShortest { - it0: a, - it1: b, - phase: false, - } -} - -impl<I, J> Iterator for InterleaveShortest<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - type Item = I::Item; - - #[inline] - fn next(&mut self) -> Option<I::Item> { - match self.phase { - false => match self.it0.next() { - None => None, - e => { - self.phase = true; - e - } - }, - true => match self.it1.next() { - None => None, - e => { - self.phase = false; - e - } - }, - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (curr_hint, next_hint) = { - let it0_hint = self.it0.size_hint(); - let it1_hint = self.it1.size_hint(); - if self.phase { - (it1_hint, it0_hint) - } else { - (it0_hint, it1_hint) - } - }; - let (curr_lower, curr_upper) = curr_hint; - let (next_lower, next_upper) = next_hint; - let (combined_lower, combined_upper) = - size_hint::mul_scalar(size_hint::min(curr_hint, next_hint), 2); - let lower = - if curr_lower > next_lower { - combined_lower + 1 - } else { - combined_lower - }; - let upper = { - let extra_elem = match (curr_upper, next_upper) { - (_, None) => false, - (None, Some(_)) => true, - (Some(curr_max), Some(next_max)) => curr_max > next_max, - }; - if extra_elem { - combined_upper.and_then(|x| x.checked_add(1)) - } else { - combined_upper - } - }; - (lower, upper) - } -} - -#[derive(Clone, Debug)] -/// An iterator adaptor that allows putting back a single -/// item to the front of the iterator. -/// -/// Iterator element type is `I::Item`. -pub struct PutBack<I> - where I: Iterator -{ - top: Option<I::Item>, - iter: I, -} - -/// Create an iterator where you can put back a single item -pub fn put_back<I>(iterable: I) -> PutBack<I::IntoIter> - where I: IntoIterator -{ - PutBack { - top: None, - iter: iterable.into_iter(), - } -} - -impl<I> PutBack<I> - where I: Iterator -{ - /// put back value `value` (builder method) - pub fn with_value(mut self, value: I::Item) -> Self { - self.put_back(value); - self - } - - /// Split the `PutBack` into its parts. - #[inline] - pub fn into_parts(self) -> (Option<I::Item>, I) { - let PutBack{top, iter} = self; - (top, iter) - } - - /// Put back a single value to the front of the iterator. - /// - /// If a value is already in the put back slot, it is overwritten. - #[inline] - pub fn put_back(&mut self, x: I::Item) { - self.top = Some(x) - } -} - -impl<I> Iterator for PutBack<I> - where I: Iterator -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - match self.top { - None => self.iter.next(), - ref mut some => some.take(), - } - } - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // Not ExactSizeIterator because size may be larger than usize - size_hint::add_scalar(self.iter.size_hint(), self.top.is_some() as usize) - } - - fn all<G>(&mut self, mut f: G) -> bool - where G: FnMut(Self::Item) -> bool - { - if let Some(elt) = self.top.take() { - if !f(elt) { - return false; - } - } - self.iter.all(f) - } - - fn fold<Acc, G>(mut self, init: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - if let Some(elt) = self.top.take() { - accum = f(accum, elt); - } - self.iter.fold(accum, f) - } -} - -#[derive(Debug, Clone)] -/// An iterator adaptor that iterates over the cartesian product of -/// the element sets of two iterators `I` and `J`. -/// -/// Iterator element type is `(I::Item, J::Item)`. -/// -/// See [`.cartesian_product()`](../trait.Itertools.html#method.cartesian_product) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Product<I, J> - where I: Iterator -{ - a: I, - a_cur: Option<I::Item>, - b: J, - b_orig: J, -} - -/// Create a new cartesian product iterator -/// -/// Iterator element type is `(I::Item, J::Item)`. -pub fn cartesian_product<I, J>(mut i: I, j: J) -> Product<I, J> - where I: Iterator, - J: Clone + Iterator, - I::Item: Clone -{ - Product { - a_cur: i.next(), - a: i, - b: j.clone(), - b_orig: j, - } -} - - -impl<I, J> Iterator for Product<I, J> - where I: Iterator, - J: Clone + Iterator, - I::Item: Clone -{ - type Item = (I::Item, J::Item); - fn next(&mut self) -> Option<(I::Item, J::Item)> { - let elt_b = match self.b.next() { - None => { - self.b = self.b_orig.clone(); - match self.b.next() { - None => return None, - Some(x) => { - self.a_cur = self.a.next(); - x - } - } - } - Some(x) => x - }; - match self.a_cur { - None => None, - Some(ref a) => { - Some((a.clone(), elt_b)) - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let has_cur = self.a_cur.is_some() as usize; - // Not ExactSizeIterator because size may be larger than usize - let (b_min, b_max) = self.b.size_hint(); - - // Compute a * b_orig + b for both lower and upper bound - size_hint::add( - size_hint::mul(self.a.size_hint(), self.b_orig.size_hint()), - (b_min * has_cur, b_max.map(move |x| x * has_cur))) - } - - fn fold<Acc, G>(mut self, mut accum: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - // use a split loop to handle the loose a_cur as well as avoiding to - // clone b_orig at the end. - if let Some(mut a) = self.a_cur.take() { - let mut b = self.b; - loop { - accum = b.fold(accum, |acc, elt| f(acc, (a.clone(), elt))); - - // we can only continue iterating a if we had a first element; - if let Some(next_a) = self.a.next() { - b = self.b_orig.clone(); - a = next_a; - } else { - break; - } - } - } - accum - } -} - -/// A “meta iterator adaptor”. Its closure recives a reference to the iterator -/// and may pick off as many elements as it likes, to produce the next iterator element. -/// -/// Iterator element type is *X*, if the return type of `F` is *Option\<X\>*. -/// -/// See [`.batching()`](../trait.Itertools.html#method.batching) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Batching<I, F> { - f: F, - iter: I, -} - -impl<I, F> fmt::Debug for Batching<I, F> where I: fmt::Debug { - debug_fmt_fields!(Batching, iter); -} - -/// Create a new Batching iterator. -pub fn batching<I, F>(iter: I, f: F) -> Batching<I, F> { - Batching { f: f, iter: iter } -} - -impl<B, F, I> Iterator for Batching<I, F> - where I: Iterator, - F: FnMut(&mut I) -> Option<B> -{ - type Item = B; - #[inline] - fn next(&mut self) -> Option<B> { - (self.f)(&mut self.iter) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // No information about closue behavior - (0, None) - } -} - -/// An iterator adaptor that steps a number elements in the base iterator -/// for each iteration. -/// -/// The iterator steps by yielding the next element from the base iterator, -/// then skipping forward *n-1* elements. -/// -/// See [`.step()`](../trait.Itertools.html#method.step) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Step<I> { - iter: Fuse<I>, - skip: usize, -} - -/// Create a `Step` iterator. -/// -/// **Panics** if the step is 0. -pub fn step<I>(iter: I, step: usize) -> Step<I> - where I: Iterator -{ - assert!(step != 0); - Step { - iter: iter.fuse(), - skip: step - 1, - } -} - -impl<I> Iterator for Step<I> - where I: Iterator -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - let elt = self.iter.next(); - if self.skip > 0 { - self.iter.nth(self.skip - 1); - } - elt - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, high) = self.iter.size_hint(); - let div = |x: usize| { - if x == 0 { - 0 - } else { - 1 + (x - 1) / (self.skip + 1) - } - }; - (div(low), high.map(div)) - } -} - -// known size -impl<I> ExactSizeIterator for Step<I> - where I: ExactSizeIterator -{} - - -struct MergeCore<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - a: Peekable<I>, - b: Peekable<J>, - fused: Option<bool>, -} - - -impl<I, J> Clone for MergeCore<I, J> - where I: Iterator, - J: Iterator<Item = I::Item>, - Peekable<I>: Clone, - Peekable<J>: Clone -{ - fn clone(&self) -> Self { - clone_fields!(MergeCore, self, a, b, fused) - } -} - -impl<I, J> MergeCore<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - fn next_with<F>(&mut self, mut less_than: F) -> Option<I::Item> - where F: FnMut(&I::Item, &I::Item) -> bool - { - let less_than = match self.fused { - Some(lt) => lt, - None => match (self.a.peek(), self.b.peek()) { - (Some(a), Some(b)) => less_than(a, b), - (Some(_), None) => { - self.fused = Some(true); - true - } - (None, Some(_)) => { - self.fused = Some(false); - false - } - (None, None) => return None, - } - }; - - if less_than { - self.a.next() - } else { - self.b.next() - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - // Not ExactSizeIterator because size may be larger than usize - size_hint::add(self.a.size_hint(), self.b.size_hint()) - } -} - -/// An iterator adaptor that merges the two base iterators in ascending order. -/// If both base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.merge()`](../trait.Itertools.html#method.merge_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Merge<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - merge: MergeCore<I, J>, -} - -impl<I, J> Clone for Merge<I, J> - where I: Iterator, - J: Iterator<Item = I::Item>, - Peekable<I>: Clone, - Peekable<J>: Clone -{ - fn clone(&self) -> Self { - clone_fields!(Merge, self, merge) - } -} - -impl<I, J> fmt::Debug for Merge<I, J> - where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Merge, merge.a, merge.b); -} - -/// Create an iterator that merges elements in `i` and `j`. -/// -/// `IntoIterator` enabled version of `i.merge(j)`. -/// -/// ``` -/// use itertools::merge; -/// -/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) { -/// /* loop body */ -/// } -/// ``` -pub fn merge<I, J>(i: I, j: J) -> Merge<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> - where I: IntoIterator, - J: IntoIterator<Item = I::Item>, - I::Item: PartialOrd -{ - Merge { - merge: MergeCore { - a: i.into_iter().peekable(), - b: j.into_iter().peekable(), - fused: None, - }, - } -} - -impl<I, J> Iterator for Merge<I, J> - where I: Iterator, - J: Iterator<Item = I::Item>, - I::Item: PartialOrd -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - self.merge.next_with(|a, b| a <= b) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.merge.size_hint() - } -} - -/// An iterator adaptor that merges the two base iterators in ascending order. -/// If both base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.merge_by()`](../trait.Itertools.html#method.merge_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MergeBy<I, J, F> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - merge: MergeCore<I, J>, - cmp: F, -} - -impl<I, J, F> fmt::Debug for MergeBy<I, J, F> - where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(MergeBy, merge.a, merge.b); -} - -/// Create a `MergeBy` iterator. -pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I, J, F> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - MergeBy { - merge: MergeCore { - a: a.peekable(), - b: b.peekable(), - fused: None, - }, - cmp: cmp, - } -} - -impl<I, J, F> Clone for MergeBy<I, J, F> - where I: Iterator, - J: Iterator<Item = I::Item>, - Peekable<I>: Clone, - Peekable<J>: Clone, - F: Clone -{ - fn clone(&self) -> Self { - clone_fields!(MergeBy, self, merge, cmp) - } -} - -impl<I, J, F> Iterator for MergeBy<I, J, F> - where I: Iterator, - J: Iterator<Item = I::Item>, - F: FnMut(&I::Item, &I::Item) -> bool -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - self.merge.next_with(&mut self.cmp) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.merge.size_hint() - } -} - -#[derive(Clone, Debug)] -pub struct CoalesceCore<I> - where I: Iterator -{ - iter: I, - last: Option<I::Item>, -} - -impl<I> CoalesceCore<I> - where I: Iterator -{ - fn next_with<F>(&mut self, mut f: F) -> Option<I::Item> - where F: FnMut(I::Item, I::Item) -> Result<I::Item, (I::Item, I::Item)> - { - // this fuses the iterator - let mut last = match self.last.take() { - None => return None, - Some(x) => x, - }; - for next in &mut self.iter { - match f(last, next) { - Ok(joined) => last = joined, - Err((last_, next_)) => { - self.last = Some(next_); - return Some(last_); - } - } - } - - Some(last) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, hi) = size_hint::add_scalar(self.iter.size_hint(), - self.last.is_some() as usize); - ((low > 0) as usize, hi) - } -} - -/// An iterator adaptor that may join together adjacent elements. -/// -/// See [`.coalesce()`](../trait.Itertools.html#method.coalesce) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Coalesce<I, F> - where I: Iterator -{ - iter: CoalesceCore<I>, - f: F, -} - -impl<I: Clone, F: Clone> Clone for Coalesce<I, F> - where I: Iterator, - I::Item: Clone -{ - fn clone(&self) -> Self { - clone_fields!(Coalesce, self, iter, f) - } -} - -impl<I, F> fmt::Debug for Coalesce<I, F> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Coalesce, iter); -} - -/// Create a new `Coalesce`. -pub fn coalesce<I, F>(mut iter: I, f: F) -> Coalesce<I, F> - where I: Iterator -{ - Coalesce { - iter: CoalesceCore { - last: iter.next(), - iter: iter, - }, - f: f, - } -} - -impl<I, F> Iterator for Coalesce<I, F> - where I: Iterator, - F: FnMut(I::Item, I::Item) -> Result<I::Item, (I::Item, I::Item)> -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - self.iter.next_with(&mut self.f) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -/// An iterator adaptor that removes repeated duplicates. -/// -/// See [`.dedup()`](../trait.Itertools.html#method.dedup) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Dedup<I> - where I: Iterator -{ - iter: CoalesceCore<I>, -} - -impl<I: Clone> Clone for Dedup<I> - where I: Iterator, - I::Item: Clone -{ - fn clone(&self) -> Self { - clone_fields!(Dedup, self, iter) - } -} - -/// Create a new `Dedup`. -pub fn dedup<I>(mut iter: I) -> Dedup<I> - where I: Iterator -{ - Dedup { - iter: CoalesceCore { - last: iter.next(), - iter: iter, - }, - } -} - -impl<I> fmt::Debug for Dedup<I> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Dedup, iter); -} - -impl<I> Iterator for Dedup<I> - where I: Iterator, - I::Item: PartialEq -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - self.iter.next_with(|x, y| { - if x == y { Ok(x) } else { Err((x, y)) } - }) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - fn fold<Acc, G>(self, mut accum: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - if let Some(mut last) = self.iter.last { - accum = self.iter.iter.fold(accum, |acc, elt| { - if elt == last { - acc - } else { - f(acc, replace(&mut last, elt)) - } - }); - f(accum, last) - } else { - accum - } - } -} - -/// An iterator adaptor that borrows from a `Clone`-able iterator -/// to only pick off elements while the predicate returns `true`. -/// -/// See [`.take_while_ref()`](../trait.Itertools.html#method.take_while_ref) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct TakeWhileRef<'a, I: 'a, F> { - iter: &'a mut I, - f: F, -} - -impl<'a, I, F> fmt::Debug for TakeWhileRef<'a, I, F> - where I: Iterator + fmt::Debug, -{ - debug_fmt_fields!(TakeWhileRef, iter); -} - -/// Create a new `TakeWhileRef` from a reference to clonable iterator. -pub fn take_while_ref<I, F>(iter: &mut I, f: F) -> TakeWhileRef<I, F> - where I: Iterator + Clone -{ - TakeWhileRef { iter: iter, f: f } -} - -impl<'a, I, F> Iterator for TakeWhileRef<'a, I, F> - where I: Iterator + Clone, - F: FnMut(&I::Item) -> bool -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - let old = self.iter.clone(); - match self.iter.next() { - None => None, - Some(elt) => { - if (self.f)(&elt) { - Some(elt) - } else { - *self.iter = old; - None - } - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, hi) = self.iter.size_hint(); - (0, hi) - } -} - -/// An iterator adaptor that filters `Option<A>` iterator elements -/// and produces `A`. Stops on the first `None` encountered. -/// -/// See [`.while_some()`](../trait.Itertools.html#method.while_some) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct WhileSome<I> { - iter: I, -} - -/// Create a new `WhileSome<I>`. -pub fn while_some<I>(iter: I) -> WhileSome<I> { - WhileSome { iter: iter } -} - -impl<I, A> Iterator for WhileSome<I> - where I: Iterator<Item = Option<A>> -{ - type Item = A; - - fn next(&mut self) -> Option<A> { - match self.iter.next() { - None | Some(None) => None, - Some(elt) => elt, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let sh = self.iter.size_hint(); - (0, sh.1) - } -} - -/// An iterator to iterate through all combinations in a `Clone`-able iterator that produces tuples -/// of a specific size. -/// -/// See [`.tuple_combinations()`](../trait.Itertools.html#method.tuple_combinations) for more -/// information. -#[derive(Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct TupleCombinations<I, T> - where I: Iterator, - T: HasCombination<I> -{ - iter: T::Combination, - _mi: PhantomData<I>, - _mt: PhantomData<T> -} - -pub trait HasCombination<I>: Sized { - type Combination: From<I> + Iterator<Item = Self>; -} - -/// Create a new `TupleCombinations` from a clonable iterator. -pub fn tuple_combinations<T, I>(iter: I) -> TupleCombinations<I, T> - where I: Iterator + Clone, - I::Item: Clone, - T: HasCombination<I>, -{ - TupleCombinations { - iter: T::Combination::from(iter), - _mi: PhantomData, - _mt: PhantomData, - } -} - -impl<I, T> Iterator for TupleCombinations<I, T> - where I: Iterator, - T: HasCombination<I>, -{ - type Item = T; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next() - } -} - -#[derive(Debug)] -pub struct Tuple1Combination<I> { - iter: I, -} - -impl<I> From<I> for Tuple1Combination<I> { - fn from(iter: I) -> Self { - Tuple1Combination { iter: iter } - } -} - -impl<I: Iterator> Iterator for Tuple1Combination<I> { - type Item = (I::Item,); - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|x| (x,)) - } -} - -impl<I: Iterator> HasCombination<I> for (I::Item,) { - type Combination = Tuple1Combination<I>; -} - -macro_rules! impl_tuple_combination { - ($C:ident $P:ident ; $A:ident, $($I:ident),* ; $($X:ident)*) => ( - #[derive(Debug)] - pub struct $C<I: Iterator> { - item: Option<I::Item>, - iter: I, - c: $P<I>, - } - - impl<I: Iterator + Clone> From<I> for $C<I> { - fn from(mut iter: I) -> Self { - $C { - item: iter.next(), - iter: iter.clone(), - c: $P::from(iter), - } - } - } - - impl<I: Iterator + Clone> From<I> for $C<Fuse<I>> { - fn from(iter: I) -> Self { - let mut iter = iter.fuse(); - $C { - item: iter.next(), - iter: iter.clone(), - c: $P::from(iter), - } - } - } - - impl<I, $A> Iterator for $C<I> - where I: Iterator<Item = $A> + Clone, - I::Item: Clone - { - type Item = ($($I),*); - - fn next(&mut self) -> Option<Self::Item> { - if let Some(($($X),*,)) = self.c.next() { - let z = self.item.clone().unwrap(); - Some((z, $($X),*)) - } else { - self.item = self.iter.next(); - self.item.clone().and_then(|z| { - self.c = $P::from(self.iter.clone()); - self.c.next().map(|($($X),*,)| (z, $($X),*)) - }) - } - } - } - - impl<I, $A> HasCombination<I> for ($($I),*) - where I: Iterator<Item = $A> + Clone, - I::Item: Clone - { - type Combination = $C<Fuse<I>>; - } - ) -} - -impl_tuple_combination!(Tuple2Combination Tuple1Combination ; A, A, A ; a); -impl_tuple_combination!(Tuple3Combination Tuple2Combination ; A, A, A, A ; a b); -impl_tuple_combination!(Tuple4Combination Tuple3Combination ; A, A, A, A, A; a b c); - - -/// An iterator adapter to simply flatten a structure. -/// -/// See [`.flatten()`](../trait.Itertools.html#method.flatten) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Flatten<I, J> { - iter: I, - front: Option<J>, -} - -/// Flatten an iterable of iterables into a single combined sequence of all -/// the elements in the iterables. -/// -/// This is more or less equivalent to `.flat_map` with an identity -/// function. -/// -/// This is an `IntoIterator`-enabled version of the [`.flatten()`][1] adaptor. -/// -/// [1]: trait.Itertools.html#method.flatten -/// -/// ``` -/// use itertools::flatten; -/// -/// let data = vec![vec![1, 2, 3], vec![4, 5, 6]]; -/// -/// itertools::assert_equal(flatten(&data), -/// &[1, 2, 3, 4, 5, 6]); -/// ``` -pub fn flatten<I, J>(iterable: I) -> Flatten<I::IntoIter, J> - where I: IntoIterator, - I::Item: IntoIterator<IntoIter=J, Item=J::Item>, - J: Iterator, -{ - Flatten { - iter: iterable.into_iter(), - front: None, - } -} - -impl<I, J> Iterator for Flatten<I, J> - where I: Iterator, - I::Item: IntoIterator<IntoIter=J, Item=J::Item>, - J: Iterator, -{ - type Item = J::Item; - fn next(&mut self) -> Option<Self::Item> { - loop { - if let Some(ref mut f) = self.front { - match f.next() { - elt @ Some(_) => return elt, - None => { } - } - } - if let Some(next_front) = self.iter.next() { - self.front = Some(next_front.into_iter()); - } else { - break; - } - } - None - } - - // special case to convert segmented iterator into consecutive loops - fn fold<Acc, G>(self, init: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - if let Some(iter) = self.front { - accum = fold(iter, accum, &mut f); - } - self.iter.fold(accum, move |accum, iter| fold(iter, accum, &mut f)) - } - -} - -/// An iterator adapter to apply a transformation within a nested `Result`. -/// -/// See [`.map_results()`](../trait.Itertools.html#method.map_results) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MapResults<I, F> { - iter: I, - f: F -} - -/// Create a new `MapResults` iterator. -pub fn map_results<I, F, T, U, E>(iter: I, f: F) -> MapResults<I, F> - where I: Iterator<Item = Result<T, E>>, - F: FnMut(T) -> U, -{ - MapResults { - iter: iter, - f: f, - } -} - -impl<I, F, T, U, E> Iterator for MapResults<I, F> - where I: Iterator<Item = Result<T, E>>, - F: FnMut(T) -> U, -{ - type Item = Result<U, E>; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|v| v.map(&mut self.f)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - let mut f = self.f; - self.iter.fold(init, move |acc, v| fold_f(acc, v.map(&mut f))) - } - - fn collect<C>(self) -> C - where C: FromIterator<Self::Item> - { - let mut f = self.f; - self.iter.map(move |v| v.map(&mut f)).collect() - } -} - -/// An iterator adapter to get the positions of each element that matches a predicate. -/// -/// See [`.positions()`](../trait.Itertools.html#method.positions) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Positions<I, F> { - iter: I, - f: F, - count: usize, -} - -/// Create a new `Positions` iterator. -pub fn positions<I, F>(iter: I, f: F) -> Positions<I, F> - where I: Iterator, - F: FnMut(I::Item) -> bool, -{ - Positions { - iter: iter, - f: f, - count: 0 - } -} - -impl<I, F> Iterator for Positions<I, F> - where I: Iterator, - F: FnMut(I::Item) -> bool, -{ - type Item = usize; - - fn next(&mut self) -> Option<Self::Item> { - while let Some(v) = self.iter.next() { - let i = self.count; - self.count = i + 1; - if (self.f)(v) { - return Some(i); - } - } - None - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (0, self.iter.size_hint().1) - } -} - -impl<I, F> DoubleEndedIterator for Positions<I, F> - where I: DoubleEndedIterator + ExactSizeIterator, - F: FnMut(I::Item) -> bool, -{ - fn next_back(&mut self) -> Option<Self::Item> { - while let Some(v) = self.iter.next_back() { - if (self.f)(v) { - return Some(self.count + self.iter.len()) - } - } - None - } -} - -/// An iterator adapter to apply a mutating function to each element before yielding it. -/// -/// See [`.update()`](../trait.Itertools.html#method.update) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Update<I, F> { - iter: I, - f: F, -} - -/// Create a new `Update` iterator. -pub fn update<I, F>(iter: I, f: F) -> Update<I, F> -where - I: Iterator, - F: FnMut(&mut I::Item), -{ - Update { iter: iter, f: f } -} - -impl<I, F> Iterator for Update<I, F> -where - I: Iterator, - F: FnMut(&mut I::Item), -{ - type Item = I::Item; - - fn next(&mut self) -> Option<Self::Item> { - if let Some(mut v) = self.iter.next() { - (self.f)(&mut v); - Some(v) - } else { - None - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - let mut f = self.f; - self.iter.fold(init, move |acc, mut v| { f(&mut v); g(acc, v) }) - } - - // if possible, re-use inner iterator specializations in collect - fn collect<C>(self) -> C - where C: FromIterator<Self::Item> - { - let mut f = self.f; - self.iter.map(move |mut v| { f(&mut v); v }).collect() - } -} - -impl<I, F> ExactSizeIterator for Update<I, F> -where - I: ExactSizeIterator, - F: FnMut(&mut I::Item), -{} - -impl<I, F> DoubleEndedIterator for Update<I, F> -where - I: DoubleEndedIterator, - F: FnMut(&mut I::Item), -{ - fn next_back(&mut self) -> Option<Self::Item> { - if let Some(mut v) = self.iter.next_back() { - (self.f)(&mut v); - Some(v) - } else { - None - } - } -} diff --git a/vendor/itertools-0.7.8/src/adaptors/multi_product.rs b/vendor/itertools-0.7.8/src/adaptors/multi_product.rs deleted file mode 100644 index a6796386ed..0000000000 --- a/vendor/itertools-0.7.8/src/adaptors/multi_product.rs +++ /dev/null @@ -1,220 +0,0 @@ -#![cfg(feature = "use_std")] - -use size_hint; -use Itertools; - -#[derive(Clone)] -/// An iterator adaptor that iterates over the cartesian product of -/// multiple iterators of type `I`. -/// -/// An iterator element type is `Vec<I>`. -/// -/// See [`.multi_cartesian_product()`](../trait.Itertools.html#method.multi_cartesian_product) -/// for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MultiProduct<I>(Vec<MultiProductIter<I>>) - where I: Iterator + Clone, - I::Item: Clone; - -/// Create a new cartesian product iterator over an arbitrary number -/// of iterators of the same type. -/// -/// Iterator element is of type `Vec<H::Item::Item>`. -pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter> - where H: Iterator, - H::Item: IntoIterator, - <H::Item as IntoIterator>::IntoIter: Clone, - <H::Item as IntoIterator>::Item: Clone -{ - MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect()) -} - -#[derive(Clone, Debug)] -/// Holds the state of a single iterator within a MultiProduct. -struct MultiProductIter<I> - where I: Iterator + Clone, - I::Item: Clone -{ - cur: Option<I::Item>, - iter: I, - iter_orig: I, -} - -/// Holds the current state during an iteration of a MultiProduct. -#[derive(Debug)] -enum MultiProductIterState { - StartOfIter, - MidIter { on_first_iter: bool }, -} - -impl<I> MultiProduct<I> - where I: Iterator + Clone, - I::Item: Clone -{ - /// Iterates the rightmost iterator, then recursively iterates iterators - /// to the left if necessary. - /// - /// Returns true if the iteration succeeded, else false. - fn iterate_last( - multi_iters: &mut [MultiProductIter<I>], - mut state: MultiProductIterState - ) -> bool { - use self::MultiProductIterState::*; - - if let Some((last, rest)) = multi_iters.split_last_mut() { - let on_first_iter = match state { - StartOfIter => { - let on_first_iter = !last.in_progress(); - state = MidIter { on_first_iter: on_first_iter }; - on_first_iter - }, - MidIter { on_first_iter } => on_first_iter - }; - - if !on_first_iter { - last.iterate(); - } - - if last.in_progress() { - true - } else if MultiProduct::iterate_last(rest, state) { - last.reset(); - last.iterate(); - // If iterator is None twice consecutively, then iterator is - // empty; whole product is empty. - last.in_progress() - } else { - false - } - } else { - // Reached end of iterator list. On initialisation, return true. - // At end of iteration (final iterator finishes), finish. - match state { - StartOfIter => false, - MidIter { on_first_iter } => on_first_iter - } - } - } - - /// Returns the unwrapped value of the next iteration. - fn curr_iterator(&self) -> Vec<I::Item> { - self.0.iter().map(|multi_iter| { - multi_iter.cur.clone().unwrap() - }).collect() - } - - /// Returns true if iteration has started and has not yet finished; false - /// otherwise. - fn in_progress(&self) -> bool { - if let Some(last) = self.0.last() { - last.in_progress() - } else { - false - } - } -} - -impl<I> MultiProductIter<I> - where I: Iterator + Clone, - I::Item: Clone -{ - fn new(iter: I) -> Self { - MultiProductIter { - cur: None, - iter: iter.clone(), - iter_orig: iter - } - } - - /// Iterate the managed iterator. - fn iterate(&mut self) { - self.cur = self.iter.next(); - } - - /// Reset the managed iterator. - fn reset(&mut self) { - self.iter = self.iter_orig.clone(); - } - - /// Returns true if the current iterator has been started and has not yet - /// finished; false otherwise. - fn in_progress(&self) -> bool { - self.cur.is_some() - } -} - -impl<I> Iterator for MultiProduct<I> - where I: Iterator + Clone, - I::Item: Clone -{ - type Item = Vec<I::Item>; - - fn next(&mut self) -> Option<Self::Item> { - if MultiProduct::iterate_last( - &mut self.0, - MultiProductIterState::StartOfIter - ) { - Some(self.curr_iterator()) - } else { - None - } - } - - fn count(self) -> usize { - if self.0.len() == 0 { - return 0; - } - - if !self.in_progress() { - return self.0.into_iter().fold(1, |acc, multi_iter| { - acc * multi_iter.iter.count() - }); - } - - self.0.into_iter().fold( - 0, - |acc, MultiProductIter { iter, iter_orig, cur: _ }| { - let total_count = iter_orig.count(); - let cur_count = iter.count(); - acc * total_count + cur_count - } - ) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - // Not ExactSizeIterator because size may be larger than usize - if self.0.len() == 0 { - return (0, Some(0)); - } - - if !self.in_progress() { - return self.0.iter().fold((1, Some(1)), |acc, multi_iter| { - size_hint::mul(acc, multi_iter.iter.size_hint()) - }); - } - - self.0.iter().fold( - (0, Some(0)), - |acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| { - let cur_size = iter.size_hint(); - let total_size = iter_orig.size_hint(); - size_hint::add(size_hint::mul(acc, total_size), cur_size) - } - ) - } - - fn last(self) -> Option<Self::Item> { - let iter_count = self.0.len(); - - let lasts: Self::Item = self.0.into_iter() - .map(|multi_iter| multi_iter.iter.last()) - .while_some() - .collect(); - - if lasts.len() == iter_count { - Some(lasts) - } else { - None - } - } -} diff --git a/vendor/itertools-0.7.8/src/combinations.rs b/vendor/itertools-0.7.8/src/combinations.rs deleted file mode 100644 index a7744151c9..0000000000 --- a/vendor/itertools-0.7.8/src/combinations.rs +++ /dev/null @@ -1,165 +0,0 @@ - -use std::ops::Index; -use std::fmt; - -/// An iterator to iterate through all the `n`-length combinations in an iterator. -/// -/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Combinations<I: Iterator> { - n: usize, - indices: Vec<usize>, - pool: LazyBuffer<I>, - first: bool, -} - -impl<I> fmt::Debug for Combinations<I> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Combinations, n, indices, pool, first); -} - -/// Create a new `Combinations` from a clonable iterator. -pub fn combinations<I>(iter: I, n: usize) -> Combinations<I> - where I: Iterator -{ - let mut indices: Vec<usize> = Vec::with_capacity(n); - for i in 0..n { - indices.push(i); - } - let mut pool: LazyBuffer<I> = LazyBuffer::new(iter); - - for _ in 0..n { - if !pool.get_next() { - break; - } - } - - Combinations { - n: n, - indices: indices, - pool: pool, - first: true, - } -} - -impl<I> Iterator for Combinations<I> - where I: Iterator, - I::Item: Clone -{ - type Item = Vec<I::Item>; - fn next(&mut self) -> Option<Self::Item> { - let mut pool_len = self.pool.len(); - if self.pool.is_done() { - if pool_len == 0 || self.n > pool_len { - return None; - } - } - - if self.first { - self.first = false; - } else if self.n == 0 { - return None; - } else { - // Scan from the end, looking for an index to increment - let mut i: usize = self.n - 1; - - // Check if we need to consume more from the iterator - if self.indices[i] == pool_len - 1 && !self.pool.is_done() { - if self.pool.get_next() { - pool_len += 1; - } - } - - while self.indices[i] == i + pool_len - self.n { - if i > 0 { - i -= 1; - } else { - // Reached the last combination - return None; - } - } - - // Increment index, and reset the ones to its right - self.indices[i] += 1; - let mut j = i + 1; - while j < self.n { - self.indices[j] = self.indices[j - 1] + 1; - j += 1; - } - } - - // Create result vector based on the indices - let mut result = Vec::with_capacity(self.n); - for i in self.indices.iter() { - result.push(self.pool[*i].clone()); - } - Some(result) - } -} - -#[derive(Debug)] -struct LazyBuffer<I: Iterator> { - it: I, - done: bool, - buffer: Vec<I::Item>, -} - -impl<I> LazyBuffer<I> - where I: Iterator -{ - pub fn new(it: I) -> LazyBuffer<I> { - let mut it = it; - let mut buffer = Vec::new(); - let done; - if let Some(first) = it.next() { - buffer.push(first); - done = false; - } else { - done = true; - } - LazyBuffer { - it: it, - done: done, - buffer: buffer, - } - } - - pub fn len(&self) -> usize { - self.buffer.len() - } - - pub fn is_done(&self) -> bool { - self.done - } - - pub fn get_next(&mut self) -> bool { - if self.done { - return false; - } - let next_item = self.it.next(); - match next_item { - Some(x) => { - self.buffer.push(x); - true - } - None => { - self.done = true; - false - } - } - } -} - -impl<I> Index<usize> for LazyBuffer<I> - where I: Iterator, - I::Item: Sized -{ - type Output = I::Item; - - fn index<'b>(&'b self, _index: usize) -> &'b I::Item { - self.buffer.index(_index) - } -} - diff --git a/vendor/itertools-0.7.8/src/concat_impl.rs b/vendor/itertools-0.7.8/src/concat_impl.rs deleted file mode 100644 index 05b370e1c6..0000000000 --- a/vendor/itertools-0.7.8/src/concat_impl.rs +++ /dev/null @@ -1,22 +0,0 @@ -use Itertools; - -/// Combine all an iterator's elements into one element by using `Extend`. -/// -/// `IntoIterator`-enabled version of `.concat()` -/// -/// This combinator will extend the first item with each of the rest of the -/// items of the iterator. If the iterator is empty, the default value of -/// `I::Item` is returned. -/// -/// ```rust -/// use itertools::concat; -/// -/// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; -/// assert_eq!(concat(input), vec![1, 2, 3, 4, 5, 6]); -/// ``` -pub fn concat<I>(iterable: I) -> I::Item - where I: IntoIterator, - I::Item: Extend<<<I as IntoIterator>::Item as IntoIterator>::Item> + IntoIterator + Default -{ - iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(|| <_>::default()) -} diff --git a/vendor/itertools-0.7.8/src/cons_tuples_impl.rs b/vendor/itertools-0.7.8/src/cons_tuples_impl.rs deleted file mode 100644 index 9b27e7580f..0000000000 --- a/vendor/itertools-0.7.8/src/cons_tuples_impl.rs +++ /dev/null @@ -1,68 +0,0 @@ - -macro_rules! impl_cons_iter( - ($_A:ident, $_B:ident, ) => (); // stop - - ($A:ident, $($B:ident,)*) => ( - impl_cons_iter!($($B,)*); - #[allow(non_snake_case)] - impl<X, Iter, $($B),*> Iterator for ConsTuples<Iter, (($($B,)*), X)> - where Iter: Iterator<Item = (($($B,)*), X)>, - { - type Item = ($($B,)* X, ); - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - fn fold<Acc, Fold>(self, accum: Acc, mut f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, ))) - } - } - - #[allow(non_snake_case)] - impl<X, Iter, $($B),*> DoubleEndedIterator for ConsTuples<Iter, (($($B,)*), X)> - where Iter: DoubleEndedIterator<Item = (($($B,)*), X)>, - { - fn next_back(&mut self) -> Option<Self::Item> { - self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) - } - } - - ); -); - -impl_cons_iter!(A, B, C, D, E, F, G, H,); - -/// An iterator that maps an iterator of tuples like -/// `((A, B), C)` to an iterator of `(A, B, C)`. -/// -/// Used by the `iproduct!()` macro. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct ConsTuples<I, J> - where I: Iterator<Item=J>, -{ - iter: I, -} - -impl<I, J> Clone for ConsTuples<I, J> - where I: Clone + Iterator<Item=J>, -{ - fn clone(&self) -> Self { - ConsTuples { - iter: self.iter.clone(), - } - } -} - -/// Create an iterator that maps for example iterators of -/// `((A, B), C)` to `(A, B, C)`. -pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I, J> - where I: Iterator<Item=J> -{ - ConsTuples { iter: iterable.into_iter() } -} diff --git a/vendor/itertools-0.7.8/src/diff.rs b/vendor/itertools-0.7.8/src/diff.rs deleted file mode 100644 index 2951bc422e..0000000000 --- a/vendor/itertools-0.7.8/src/diff.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! "Diff"ing iterators for caching elements to sequential collections without requiring the new -//! elements' iterator to be `Clone`. -//! -//! - [**Diff**](./enum.Diff.html) (produced by the [**diff_with**](./fn.diff_with.html) function) -//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from -//! a lock-step comparison. - -use free::put_back; -use structs::PutBack; - -/// A type returned by the [`diff_with`](./fn.diff_with.html) function. -/// -/// `Diff` represents the way in which the elements yielded by the iterator `I` differ to some -/// iterator `J`. -pub enum Diff<I, J> - where I: Iterator, - J: Iterator -{ - /// The index of the first non-matching element along with both iterator's remaining elements - /// starting with the first mis-match. - FirstMismatch(usize, PutBack<I>, PutBack<J>), - /// The total number of elements that were in `J` along with the remaining elements of `I`. - Shorter(usize, PutBack<I>), - /// The total number of elements that were in `I` along with the remaining elements of `J`. - Longer(usize, PutBack<J>), -} - -/// Compares every element yielded by both `i` and `j` with the given function in lock-step and -/// returns a `Diff` which describes how `j` differs from `i`. -/// -/// If the number of elements yielded by `j` is less than the number of elements yielded by `i`, -/// the number of `j` elements yielded will be returned along with `i`'s remaining elements as -/// `Diff::Shorter`. -/// -/// If the two elements of a step differ, the index of those elements along with the remaining -/// elements of both `i` and `j` are returned as `Diff::FirstMismatch`. -/// -/// If `i` becomes exhausted before `j` becomes exhausted, the number of elements in `i` along with -/// the remaining `j` elements will be returned as `Diff::Longer`. -pub fn diff_with<I, J, F>(i: I, j: J, is_equal: F) - -> Option<Diff<I::IntoIter, J::IntoIter>> - where I: IntoIterator, - J: IntoIterator, - F: Fn(&I::Item, &J::Item) -> bool -{ - let mut i = i.into_iter(); - let mut j = j.into_iter(); - let mut idx = 0; - while let Some(i_elem) = i.next() { - match j.next() { - None => return Some(Diff::Shorter(idx, put_back(i).with_value(i_elem))), - Some(j_elem) => if !is_equal(&i_elem, &j_elem) { - let remaining_i = put_back(i).with_value(i_elem); - let remaining_j = put_back(j).with_value(j_elem); - return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j)); - }, - } - idx += 1; - } - j.next().map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem))) -} diff --git a/vendor/itertools-0.7.8/src/either_or_both.rs b/vendor/itertools-0.7.8/src/either_or_both.rs deleted file mode 100644 index 9f0f3133e7..0000000000 --- a/vendor/itertools-0.7.8/src/either_or_both.rs +++ /dev/null @@ -1,10 +0,0 @@ -/// Value that either holds a single A or B, or both. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum EitherOrBoth<A, B> { - /// Both values are present. - Both(A, B), - /// Only the left value of type `A` is present. - Left(A), - /// Only the right value of type `B` is present. - Right(B), -} diff --git a/vendor/itertools-0.7.8/src/format.rs b/vendor/itertools-0.7.8/src/format.rs deleted file mode 100644 index c42806b01c..0000000000 --- a/vendor/itertools-0.7.8/src/format.rs +++ /dev/null @@ -1,113 +0,0 @@ -use std::fmt; -use std::cell::RefCell; - -/// Format all iterator elements lazily, separated by `sep`. -/// -/// The format value can only be formatted once, after that the iterator is -/// exhausted. -/// -/// See [`.format_with()`](../trait.Itertools.html#method.format_with) for more information. -pub struct FormatWith<'a, I, F> { - sep: &'a str, - /// FormatWith uses interior mutability because Display::fmt takes &self. - inner: RefCell<Option<(I, F)>>, -} - -/// Format all iterator elements lazily, separated by `sep`. -/// -/// The format value can only be formatted once, after that the iterator is -/// exhausted. -/// -/// See [`.format()`](../trait.Itertools.html#method.format) -/// for more information. -#[derive(Clone)] -pub struct Format<'a, I> { - sep: &'a str, - /// Format uses interior mutability because Display::fmt takes &self. - inner: RefCell<Option<I>>, -} - -pub fn new_format<'a, I, F>(iter: I, separator: &'a str, f: F) -> FormatWith<'a, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result -{ - FormatWith { - sep: separator, - inner: RefCell::new(Some((iter, f))), - } -} - -pub fn new_format_default<'a, I>(iter: I, separator: &'a str) -> Format<'a, I> - where I: Iterator, -{ - Format { - sep: separator, - inner: RefCell::new(Some(iter)), - } -} - -impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (mut iter, mut format) = match self.inner.borrow_mut().take() { - Some(t) => t, - None => panic!("FormatWith: was already formatted once"), - }; - - if let Some(fst) = iter.next() { - try!(format(fst, &mut |disp: &fmt::Display| disp.fmt(f))); - for elt in iter { - if self.sep.len() > 0 { - - try!(f.write_str(self.sep)); - } - try!(format(elt, &mut |disp: &fmt::Display| disp.fmt(f))); - } - } - Ok(()) - } -} - -impl<'a, I> Format<'a, I> - where I: Iterator, -{ - fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result - where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, - { - let mut iter = match self.inner.borrow_mut().take() { - Some(t) => t, - None => panic!("Format: was already formatted once"), - }; - - if let Some(fst) = iter.next() { - try!(cb(&fst, f)); - for elt in iter { - if self.sep.len() > 0 { - try!(f.write_str(self.sep)); - } - try!(cb(&elt, f)); - } - } - Ok(()) - } -} - -macro_rules! impl_format { - ($($fmt_trait:ident)*) => { - $( - impl<'a, I> fmt::$fmt_trait for Format<'a, I> - where I: Iterator, - I::Item: fmt::$fmt_trait, - { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f, fmt::$fmt_trait::fmt) - } - } - )* - } -} - -impl_format!{Display Debug - UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} diff --git a/vendor/itertools-0.7.8/src/free.rs b/vendor/itertools-0.7.8/src/free.rs deleted file mode 100644 index 1563679f9d..0000000000 --- a/vendor/itertools-0.7.8/src/free.rs +++ /dev/null @@ -1,231 +0,0 @@ -//! Free functions that create iterator adaptors or call iterator methods. -//! -//! The benefit of free functions is that they accept any `IntoIterator` as -//! argument, so the resulting code may be easier to read. - -#[cfg(feature = "use_std")] -use std::fmt::Display; -use std::iter::{self, Zip}; -#[cfg(feature = "use_std")] -use Itertools; - -pub use adaptors::{ - interleave, - merge, - put_back, -}; -#[cfg(feature = "use_std")] -pub use put_back_n_impl::put_back_n; -#[cfg(feature = "use_std")] -pub use multipeek_impl::multipeek; -#[cfg(feature = "use_std")] -pub use kmerge_impl::kmerge; -pub use zip_eq_impl::zip_eq; -pub use merge_join::merge_join_by; -#[cfg(feature = "use_std")] -pub use rciter_impl::rciter; - -/// Iterate `iterable` with a running index. -/// -/// `IntoIterator` enabled version of `.enumerate()`. -/// -/// ``` -/// use itertools::enumerate; -/// -/// for (i, elt) in enumerate(&[1, 2, 3]) { -/// /* loop body */ -/// } -/// ``` -pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter> - where I: IntoIterator -{ - iterable.into_iter().enumerate() -} - -/// Iterate `iterable` in reverse. -/// -/// `IntoIterator` enabled version of `.rev()`. -/// -/// ``` -/// use itertools::rev; -/// -/// for elt in rev(&[1, 2, 3]) { -/// /* loop body */ -/// } -/// ``` -pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter> - where I: IntoIterator, - I::IntoIter: DoubleEndedIterator -{ - iterable.into_iter().rev() -} - -/// Iterate `i` and `j` in lock step. -/// -/// `IntoIterator` enabled version of `i.zip(j)`. -/// -/// ``` -/// use itertools::zip; -/// -/// let data = [1, 2, 3, 4, 5]; -/// for (a, b) in zip(&data, &data[1..]) { -/// /* loop body */ -/// } -/// ``` -pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter> - where I: IntoIterator, - J: IntoIterator -{ - i.into_iter().zip(j) -} - -/// Create an iterator that first iterates `i` and then `j`. -/// -/// `IntoIterator` enabled version of `i.chain(j)`. -/// -/// ``` -/// use itertools::chain; -/// -/// for elt in chain(&[1, 2, 3], &[4]) { -/// /* loop body */ -/// } -/// ``` -pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> - where I: IntoIterator, - J: IntoIterator<Item = I::Item> -{ - i.into_iter().chain(j) -} - -/// Create an iterator that clones each element from &T to T -/// -/// `IntoIterator` enabled version of `i.cloned()`. -/// -/// ``` -/// use itertools::cloned; -/// -/// assert_eq!(cloned(b"abc").next(), Some(b'a')); -/// ``` -pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter> - where I: IntoIterator<Item=&'a T>, - T: Clone, -{ - iterable.into_iter().cloned() -} - -/// Perform a fold operation over the iterable. -/// -/// `IntoIterator` enabled version of `i.fold(init, f)` -/// -/// ``` -/// use itertools::fold; -/// -/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.); -/// ``` -pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B - where I: IntoIterator, - F: FnMut(B, I::Item) -> B -{ - iterable.into_iter().fold(init, f) -} - -/// Test whether the predicate holds for all elements in the iterable. -/// -/// `IntoIterator` enabled version of `i.all(f)` -/// -/// ``` -/// use itertools::all; -/// -/// assert!(all(&[1, 2, 3], |elt| *elt > 0)); -/// ``` -pub fn all<I, F>(iterable: I, f: F) -> bool - where I: IntoIterator, - F: FnMut(I::Item) -> bool -{ - iterable.into_iter().all(f) -} - -/// Test whether the predicate holds for any elements in the iterable. -/// -/// `IntoIterator` enabled version of `i.any(f)` -/// -/// ``` -/// use itertools::any; -/// -/// assert!(any(&[0, -1, 2], |elt| *elt > 0)); -/// ``` -pub fn any<I, F>(iterable: I, f: F) -> bool - where I: IntoIterator, - F: FnMut(I::Item) -> bool -{ - iterable.into_iter().any(f) -} - -/// Return the maximum value of the iterable. -/// -/// `IntoIterator` enabled version of `i.max()`. -/// -/// ``` -/// use itertools::max; -/// -/// assert_eq!(max(0..10), Some(9)); -/// ``` -pub fn max<I>(iterable: I) -> Option<I::Item> - where I: IntoIterator, - I::Item: Ord -{ - iterable.into_iter().max() -} - -/// Return the minimum value of the iterable. -/// -/// `IntoIterator` enabled version of `i.min()`. -/// -/// ``` -/// use itertools::min; -/// -/// assert_eq!(min(0..10), Some(0)); -/// ``` -pub fn min<I>(iterable: I) -> Option<I::Item> - where I: IntoIterator, - I::Item: Ord -{ - iterable.into_iter().min() -} - - -/// Combine all iterator elements into one String, seperated by `sep`. -/// -/// `IntoIterator` enabled version of `iterable.join(sep)`. -/// -/// ``` -/// use itertools::join; -/// -/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3"); -/// ``` -#[cfg(feature = "use_std")] -pub fn join<I>(iterable: I, sep: &str) -> String - where I: IntoIterator, - I::Item: Display -{ - iterable.into_iter().join(sep) -} - -/// Collect all the iterable's elements into a sorted vector in ascending order. -/// -/// `IntoIterator` enabled version of `iterable.sorted()`. -/// -/// ``` -/// use itertools::sorted; -/// use itertools::assert_equal; -/// -/// assert_equal(sorted("rust".chars()), "rstu".chars()); -/// ``` -#[cfg(feature = "use_std")] -pub fn sorted<I>(iterable: I) -> Vec<I::Item> - where I: IntoIterator, - I::Item: Ord -{ - iterable.into_iter().sorted() -} - diff --git a/vendor/itertools-0.7.8/src/group_map.rs b/vendor/itertools-0.7.8/src/group_map.rs deleted file mode 100644 index be9f8420d8..0000000000 --- a/vendor/itertools-0.7.8/src/group_map.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![cfg(feature = "use_std")] - -use std::collections::HashMap; -use std::hash::Hash; -use std::iter::Iterator; - -/// Return a `HashMap` of keys mapped to a list of their corresponding values. -/// -/// See [`.into_group_map()`](../trait.Itertools.html#method.into_group_map) -/// for more information. -pub fn into_group_map<I, K, V>(iter: I) -> HashMap<K, Vec<V>> - where I: Iterator<Item=(K, V)>, - K: Hash + Eq, -{ - let mut lookup = HashMap::new(); - - for (key, val) in iter { - lookup.entry(key).or_insert(Vec::new()).push(val); - } - - lookup -} \ No newline at end of file diff --git a/vendor/itertools-0.7.8/src/groupbylazy.rs b/vendor/itertools-0.7.8/src/groupbylazy.rs deleted file mode 100644 index ff253e845d..0000000000 --- a/vendor/itertools-0.7.8/src/groupbylazy.rs +++ /dev/null @@ -1,571 +0,0 @@ -use std::cell::{Cell, RefCell}; -use std::vec; - -/// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks -trait KeyFunction<A> { - type Key; - fn call_mut(&mut self, arg: A) -> Self::Key; -} - -impl<'a, A, K, F: ?Sized> KeyFunction<A> for F - where F: FnMut(A) -> K -{ - type Key = K; - #[inline] - fn call_mut(&mut self, arg: A) -> Self::Key { - (*self)(arg) - } -} - - -/// ChunkIndex acts like the grouping key function for IntoChunks -#[derive(Debug)] -struct ChunkIndex { - size: usize, - index: usize, - key: usize, -} - -impl ChunkIndex { - #[inline(always)] - fn new(size: usize) -> Self { - ChunkIndex { - size: size, - index: 0, - key: 0, - } - } -} - -impl<'a, A> KeyFunction<A> for ChunkIndex { - type Key = usize; - #[inline(always)] - fn call_mut(&mut self, _arg: A) -> Self::Key { - if self.index == self.size { - self.key += 1; - self.index = 0; - } - self.index += 1; - self.key - } -} - - -struct GroupInner<K, I, F> - where I: Iterator -{ - key: F, - iter: I, - current_key: Option<K>, - current_elt: Option<I::Item>, - /// flag set if iterator is exhausted - done: bool, - /// Index of group we are currently buffering or visiting - top_group: usize, - /// Least index for which we still have elements buffered - oldest_buffered_group: usize, - /// Group index for `buffer[0]` -- the slots - /// bottom_group..oldest_buffered_group are unused and will be erased when - /// that range is large enough. - bottom_group: usize, - /// Buffered groups, from `bottom_group` (index 0) to `top_group`. - buffer: Vec<vec::IntoIter<I::Item>>, - /// index of last group iter that was dropped, usize::MAX == none - dropped_group: usize, -} - -impl<K, I, F> GroupInner<K, I, F> - where I: Iterator, - F: for<'a> KeyFunction<&'a I::Item, Key=K>, - K: PartialEq, -{ - /// `client`: Index of group that requests next element - #[inline(always)] - fn step(&mut self, client: usize) -> Option<I::Item> { - /* - println!("client={}, bottom_group={}, oldest_buffered_group={}, top_group={}, buffers=[{}]", - client, self.bottom_group, self.oldest_buffered_group, - self.top_group, - self.buffer.iter().map(|elt| elt.len()).format(", ")); - */ - if client < self.oldest_buffered_group { - None - } else if client < self.top_group || - (client == self.top_group && - self.buffer.len() > self.top_group - self.bottom_group) - { - self.lookup_buffer(client) - } else if self.done { - None - } else if self.top_group == client { - self.step_current() - } else { - self.step_buffering(client) - } - } - - #[inline(never)] - fn lookup_buffer(&mut self, client: usize) -> Option<I::Item> { - // if `bufidx` doesn't exist in self.buffer, it might be empty - let bufidx = client - self.bottom_group; - if client < self.oldest_buffered_group { - return None; - } - let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next()); - if elt.is_none() && client == self.oldest_buffered_group { - // FIXME: VecDeque is unfortunately not zero allocation when empty, - // so we do this job manually. - // `bottom_group..oldest_buffered_group` is unused, and if it's large enough, erase it. - self.oldest_buffered_group += 1; - // skip forward further empty queues too - while self.buffer.get(self.oldest_buffered_group - self.bottom_group) - .map_or(false, |buf| buf.len() == 0) - { - self.oldest_buffered_group += 1; - } - - let nclear = self.oldest_buffered_group - self.bottom_group; - if nclear > 0 && nclear >= self.buffer.len() / 2 { - let mut i = 0; - self.buffer.retain(|buf| { - i += 1; - debug_assert!(buf.len() == 0 || i > nclear); - i > nclear - }); - self.bottom_group = self.oldest_buffered_group; - } - } - elt - } - - /// Take the next element from the iterator, and set the done - /// flag if exhausted. Must not be called after done. - #[inline(always)] - fn next_element(&mut self) -> Option<I::Item> { - debug_assert!(!self.done); - match self.iter.next() { - None => { self.done = true; None } - otherwise => otherwise, - } - } - - - #[inline(never)] - fn step_buffering(&mut self, client: usize) -> Option<I::Item> { - // requested a later group -- walk through the current group up to - // the requested group index, and buffer the elements (unless - // the group is marked as dropped). - // Because the `Groups` iterator is always the first to request - // each group index, client is the next index efter top_group. - debug_assert!(self.top_group + 1 == client); - let mut group = Vec::new(); - - if let Some(elt) = self.current_elt.take() { - if self.top_group != self.dropped_group { - group.push(elt); - } - } - let mut first_elt = None; // first element of the next group - - while let Some(elt) = self.next_element() { - let key = self.key.call_mut(&elt); - match self.current_key.take() { - None => {} - Some(old_key) => if old_key != key { - self.current_key = Some(key); - first_elt = Some(elt); - break; - }, - } - self.current_key = Some(key); - if self.top_group != self.dropped_group { - group.push(elt); - } - } - - if self.top_group != self.dropped_group { - self.push_next_group(group); - } - if first_elt.is_some() { - self.top_group += 1; - debug_assert!(self.top_group == client); - } - first_elt - } - - fn push_next_group(&mut self, group: Vec<I::Item>) { - // When we add a new buffered group, fill up slots between oldest_buffered_group and top_group - while self.top_group - self.bottom_group > self.buffer.len() { - if self.buffer.is_empty() { - self.bottom_group += 1; - self.oldest_buffered_group += 1; - } else { - self.buffer.push(Vec::new().into_iter()); - } - } - self.buffer.push(group.into_iter()); - debug_assert!(self.top_group + 1 - self.bottom_group == self.buffer.len()); - } - - /// This is the immediate case, where we use no buffering - #[inline] - fn step_current(&mut self) -> Option<I::Item> { - debug_assert!(!self.done); - if let elt @ Some(..) = self.current_elt.take() { - return elt; - } - match self.next_element() { - None => None, - Some(elt) => { - let key = self.key.call_mut(&elt); - match self.current_key.take() { - None => {} - Some(old_key) => if old_key != key { - self.current_key = Some(key); - self.current_elt = Some(elt); - self.top_group += 1; - return None; - }, - } - self.current_key = Some(key); - Some(elt) - } - } - } - - /// Request the just started groups' key. - /// - /// `client`: Index of group - /// - /// **Panics** if no group key is available. - fn group_key(&mut self, client: usize) -> K { - // This can only be called after we have just returned the first - // element of a group. - // Perform this by simply buffering one more element, grabbing the - // next key. - debug_assert!(!self.done); - debug_assert!(client == self.top_group); - debug_assert!(self.current_key.is_some()); - debug_assert!(self.current_elt.is_none()); - let old_key = self.current_key.take().unwrap(); - if let Some(elt) = self.next_element() { - let key = self.key.call_mut(&elt); - if old_key != key { - self.top_group += 1; - } - self.current_key = Some(key); - self.current_elt = Some(elt); - } - old_key - } -} - -impl<K, I, F> GroupInner<K, I, F> - where I: Iterator, -{ - /// Called when a group is dropped - fn drop_group(&mut self, client: usize) { - // It's only useful to track the maximal index - if self.dropped_group == !0 || client > self.dropped_group { - self.dropped_group = client; - } - } -} - -/// `GroupBy` is the storage for the lazy grouping operation. -/// -/// If the groups are consumed in their original order, or if each -/// group is dropped without keeping it around, then `GroupBy` uses -/// no allocations. It needs allocations only if several group iterators -/// are alive at the same time. -/// -/// This type implements `IntoIterator` (it is **not** an iterator -/// itself), because the group iterators need to borrow from this -/// value. It should be stored in a local variable or temporary and -/// iterated. -/// -/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct GroupBy<K, I, F> - where I: Iterator, -{ - inner: RefCell<GroupInner<K, I, F>>, - // the group iterator's current index. Keep this in the main value - // so that simultaneous iterators all use the same state. - index: Cell<usize>, -} - -/// Create a new -pub fn new<K, J, F>(iter: J, f: F) -> GroupBy<K, J::IntoIter, F> - where J: IntoIterator, - F: FnMut(&J::Item) -> K, -{ - GroupBy { - inner: RefCell::new(GroupInner { - key: f, - iter: iter.into_iter(), - current_key: None, - current_elt: None, - done: false, - top_group: 0, - oldest_buffered_group: 0, - bottom_group: 0, - buffer: Vec::new(), - dropped_group: !0, - }), - index: Cell::new(0), - } -} - -impl<K, I, F> GroupBy<K, I, F> - where I: Iterator, -{ - /// `client`: Index of group that requests next element - fn step(&self, client: usize) -> Option<I::Item> - where F: FnMut(&I::Item) -> K, - K: PartialEq, - { - self.inner.borrow_mut().step(client) - } - - /// `client`: Index of group - fn drop_group(&self, client: usize) { - self.inner.borrow_mut().drop_group(client) - } -} - -impl<'a, K, I, F> IntoIterator for &'a GroupBy<K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq -{ - type Item = (K, Group<'a, K, I, F>); - type IntoIter = Groups<'a, K, I, F>; - - fn into_iter(self) -> Self::IntoIter { - Groups { parent: self } - } -} - - -/// An iterator that yields the Group iterators. -/// -/// Iterator element type is `(K, Group)`: -/// the group's key `K` and the group's iterator. -/// -/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Groups<'a, K: 'a, I: 'a, F: 'a> - where I: Iterator, - I::Item: 'a -{ - parent: &'a GroupBy<K, I, F>, -} - -impl<'a, K, I, F> Iterator for Groups<'a, K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq -{ - type Item = (K, Group<'a, K, I, F>); - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - let index = self.parent.index.get(); - self.parent.index.set(index + 1); - let inner = &mut *self.parent.inner.borrow_mut(); - inner.step(index).map(|elt| { - let key = inner.group_key(index); - (key, Group { - parent: self.parent, - index: index, - first: Some(elt), - }) - }) - } -} - -/// An iterator for the elements in a single group. -/// -/// Iterator element type is `I::Item`. -pub struct Group<'a, K: 'a, I: 'a, F: 'a> - where I: Iterator, - I::Item: 'a, -{ - parent: &'a GroupBy<K, I, F>, - index: usize, - first: Option<I::Item>, -} - -impl<'a, K, I, F> Drop for Group<'a, K, I, F> - where I: Iterator, - I::Item: 'a, -{ - fn drop(&mut self) { - self.parent.drop_group(self.index); - } -} - -impl<'a, K, I, F> Iterator for Group<'a, K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq, -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<Self::Item> { - if let elt @ Some(..) = self.first.take() { - return elt; - } - self.parent.step(self.index) - } -} - -///// IntoChunks ///// - -/// Create a new -pub fn new_chunks<J>(iter: J, size: usize) -> IntoChunks<J::IntoIter> - where J: IntoIterator, -{ - IntoChunks { - inner: RefCell::new(GroupInner { - key: ChunkIndex::new(size), - iter: iter.into_iter(), - current_key: None, - current_elt: None, - done: false, - top_group: 0, - oldest_buffered_group: 0, - bottom_group: 0, - buffer: Vec::new(), - dropped_group: !0, - }), - index: Cell::new(0), - } -} - - -/// `ChunkLazy` is the storage for a lazy chunking operation. -/// -/// `IntoChunks` behaves just like `GroupBy`: it is iterable, and -/// it only buffers if several chunk iterators are alive at the same time. -/// -/// This type implements `IntoIterator` (it is **not** an iterator -/// itself), because the chunk iterators need to borrow from this -/// value. It should be stored in a local variable or temporary and -/// iterated. -/// -/// Iterator element type is `Chunk`, each chunk's iterator. -/// -/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct IntoChunks<I> - where I: Iterator, -{ - inner: RefCell<GroupInner<usize, I, ChunkIndex>>, - // the chunk iterator's current index. Keep this in the main value - // so that simultaneous iterators all use the same state. - index: Cell<usize>, -} - - -impl<I> IntoChunks<I> - where I: Iterator, -{ - /// `client`: Index of chunk that requests next element - fn step(&self, client: usize) -> Option<I::Item> { - self.inner.borrow_mut().step(client) - } - - /// `client`: Index of chunk - fn drop_group(&self, client: usize) { - self.inner.borrow_mut().drop_group(client) - } -} - -impl<'a, I> IntoIterator for &'a IntoChunks<I> - where I: Iterator, - I::Item: 'a, -{ - type Item = Chunk<'a, I>; - type IntoIter = Chunks<'a, I>; - - fn into_iter(self) -> Self::IntoIter { - Chunks { - parent: self, - } - } -} - - -/// An iterator that yields the Chunk iterators. -/// -/// Iterator element type is `Chunk`. -/// -/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Chunks<'a, I: 'a> - where I: Iterator, - I::Item: 'a, -{ - parent: &'a IntoChunks<I>, -} - -impl<'a, I> Iterator for Chunks<'a, I> - where I: Iterator, - I::Item: 'a, -{ - type Item = Chunk<'a, I>; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - let index = self.parent.index.get(); - self.parent.index.set(index + 1); - let inner = &mut *self.parent.inner.borrow_mut(); - inner.step(index).map(|elt| { - Chunk { - parent: self.parent, - index: index, - first: Some(elt), - } - }) - } -} - -/// An iterator for the elements in a single chunk. -/// -/// Iterator element type is `I::Item`. -pub struct Chunk<'a, I: 'a> - where I: Iterator, - I::Item: 'a, -{ - parent: &'a IntoChunks<I>, - index: usize, - first: Option<I::Item>, -} - -impl<'a, I> Drop for Chunk<'a, I> - where I: Iterator, - I::Item: 'a, -{ - fn drop(&mut self) { - self.parent.drop_group(self.index); - } -} - -impl<'a, I> Iterator for Chunk<'a, I> - where I: Iterator, - I::Item: 'a, -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<Self::Item> { - if let elt @ Some(..) = self.first.take() { - return elt; - } - self.parent.step(self.index) - } -} diff --git a/vendor/itertools-0.7.8/src/impl_macros.rs b/vendor/itertools-0.7.8/src/impl_macros.rs deleted file mode 100644 index b41760aee8..0000000000 --- a/vendor/itertools-0.7.8/src/impl_macros.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! -//! Implementation's internal macros - -macro_rules! debug_fmt_fields { - ($tyname:ident, $($($field:ident).+),*) => { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(stringify!($tyname)) - $( - .field(stringify!($($field).+), &self.$($field).+) - )* - .finish() - } - } -} diff --git a/vendor/itertools-0.7.8/src/intersperse.rs b/vendor/itertools-0.7.8/src/intersperse.rs deleted file mode 100644 index b1dc732117..0000000000 --- a/vendor/itertools-0.7.8/src/intersperse.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::iter::Fuse; -use super::size_hint; - -#[derive(Clone)] -/// An iterator adaptor to insert a particular value -/// between each element of the adapted iterator. -/// -/// Iterator element type is `I::Item` -/// -/// This iterator is *fused*. -/// -/// See [`.intersperse()`](../trait.Itertools.html#method.intersperse) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct Intersperse<I> - where I: Iterator -{ - element: I::Item, - iter: Fuse<I>, - peek: Option<I::Item>, -} - -/// Create a new Intersperse iterator -pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I> - where I: Iterator -{ - let mut iter = iter.fuse(); - Intersperse { - peek: iter.next(), - iter: iter, - element: elt, - } -} - -impl<I> Iterator for Intersperse<I> - where I: Iterator, - I::Item: Clone -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - if self.peek.is_some() { - self.peek.take() - } else { - self.peek = self.iter.next(); - if self.peek.is_some() { - Some(self.element.clone()) - } else { - None - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - // 2 * SH + { 1 or 0 } - let has_peek = self.peek.is_some() as usize; - let sh = self.iter.size_hint(); - size_hint::add_scalar(size_hint::add(sh, sh), has_peek) - } -} diff --git a/vendor/itertools-0.7.8/src/kmerge_impl.rs b/vendor/itertools-0.7.8/src/kmerge_impl.rs deleted file mode 100644 index 0720899e37..0000000000 --- a/vendor/itertools-0.7.8/src/kmerge_impl.rs +++ /dev/null @@ -1,256 +0,0 @@ - -use size_hint; -use Itertools; - -use std::mem::replace; -use std::fmt; - -macro_rules! clone_fields { - ($name:ident, $base:expr, $($field:ident),+) => ( - $name { - $( - $field : $base . $field .clone() - ),* - } - ); -} - -/// Head element and Tail iterator pair -/// -/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on -/// first items (which are guaranteed to exist). -/// -/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in -/// `KMerge` into a min-heap. -#[derive(Debug)] -struct HeadTail<I> - where I: Iterator -{ - head: I::Item, - tail: I, -} - -impl<I> HeadTail<I> - where I: Iterator -{ - /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty. - fn new(mut it: I) -> Option<HeadTail<I>> { - let head = it.next(); - head.map(|h| { - HeadTail { - head: h, - tail: it, - } - }) - } - - /// Get the next element and update `head`, returning the old head in `Some`. - /// - /// Returns `None` when the tail is exhausted (only `head` then remains). - fn next(&mut self) -> Option<I::Item> { - if let Some(next) = self.tail.next() { - Some(replace(&mut self.head, next)) - } else { - None - } - } - - /// Hints at the size of the sequence, same as the `Iterator` method. - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add_scalar(self.tail.size_hint(), 1) - } -} - -impl<I> Clone for HeadTail<I> - where I: Iterator + Clone, - I::Item: Clone -{ - fn clone(&self) -> Self { - clone_fields!(HeadTail, self, head, tail) - } -} - -/// Make `data` a heap (min-heap w.r.t the sorting). -fn heapify<T, S>(data: &mut [T], mut less_than: S) - where S: FnMut(&T, &T) -> bool -{ - for i in (0..data.len() / 2).rev() { - sift_down(data, i, &mut less_than); - } -} - -/// Sift down element at `index` (`heap` is a min-heap wrt the ordering) -fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S) - where S: FnMut(&T, &T) -> bool -{ - debug_assert!(index <= heap.len()); - let mut pos = index; - let mut child = 2 * pos + 1; - // the `pos` conditional is to avoid a bounds check - while pos < heap.len() && child < heap.len() { - let right = child + 1; - - // pick the smaller of the two children - if right < heap.len() && less_than(&heap[right], &heap[child]) { - child = right; - } - - // sift down is done if we are already in order - if !less_than(&heap[child], &heap[pos]) { - return; - } - heap.swap(pos, child); - pos = child; - child = 2 * pos + 1; - } -} - -/// An iterator adaptor that merges an abitrary number of base iterators in ascending order. -/// If all base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct KMerge<I> - where I: Iterator -{ - heap: Vec<HeadTail<I>>, -} - -impl<I> fmt::Debug for KMerge<I> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(KMerge, heap); -} - -/// Create an iterator that merges elements of the contained iterators using -/// the ordering function. -/// -/// Equivalent to `iterable.into_iter().kmerge()`. -/// -/// ``` -/// use itertools::kmerge; -/// -/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) { -/// /* loop body */ -/// } -/// ``` -pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter> - where I: IntoIterator, - I::Item: IntoIterator, - <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd -{ - let iter = iterable.into_iter(); - let (lower, _) = iter.size_hint(); - let mut heap = Vec::with_capacity(lower); - heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter()))); - heapify(&mut heap, |a, b| a.head < b.head); - KMerge { heap: heap } -} - -impl<I> Clone for KMerge<I> - where I: Iterator + Clone, - I::Item: Clone -{ - fn clone(&self) -> KMerge<I> { - clone_fields!(KMerge, self, heap) - } -} - -impl<I> Iterator for KMerge<I> - where I: Iterator, - I::Item: PartialOrd -{ - type Item = I::Item; - - fn next(&mut self) -> Option<Self::Item> { - if self.heap.is_empty() { - return None; - } - let result = if let Some(next) = self.heap[0].next() { - next - } else { - self.heap.swap_remove(0).head - }; - sift_down(&mut self.heap, 0, |a, b| a.head < b.head); - Some(result) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.heap.iter() - .map(|i| i.size_hint()) - .fold1(size_hint::add) - .unwrap_or((0, Some(0))) - } -} - -/// An iterator adaptor that merges an abitrary number of base iterators -/// according to an ordering function. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more -/// information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct KMergeBy<I, F> - where I: Iterator, -{ - heap: Vec<HeadTail<I>>, - less_than: F, -} - -impl<I, F> fmt::Debug for KMergeBy<I, F> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(KMergeBy, heap); -} - -/// Create an iterator that merges elements of the contained iterators. -/// -/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`. -pub fn kmerge_by<I, F>(iterable: I, mut less_than: F) - -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F> - where I: IntoIterator, - I::Item: IntoIterator, - F: FnMut(&<<I as IntoIterator>::Item as IntoIterator>::Item, - &<<I as IntoIterator>::Item as IntoIterator>::Item) -> bool -{ - let iter = iterable.into_iter(); - let (lower, _) = iter.size_hint(); - let mut heap: Vec<_> = Vec::with_capacity(lower); - heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter()))); - heapify(&mut heap, |a, b| less_than(&a.head, &b.head)); - KMergeBy { heap: heap, less_than: less_than } -} - - -impl<I, F> Iterator for KMergeBy<I, F> - where I: Iterator, - F: FnMut(&I::Item, &I::Item) -> bool -{ - type Item = I::Item; - - fn next(&mut self) -> Option<Self::Item> { - if self.heap.is_empty() { - return None; - } - let result = if let Some(next) = self.heap[0].next() { - next - } else { - self.heap.swap_remove(0).head - }; - let less_than = &mut self.less_than; - sift_down(&mut self.heap, 0, |a, b| less_than(&a.head, &b.head)); - Some(result) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.heap.iter() - .map(|i| i.size_hint()) - .fold1(size_hint::add) - .unwrap_or((0, Some(0))) - } -} diff --git a/vendor/itertools-0.7.8/src/lib.rs b/vendor/itertools-0.7.8/src/lib.rs deleted file mode 100644 index 32b5f7156b..0000000000 --- a/vendor/itertools-0.7.8/src/lib.rs +++ /dev/null @@ -1,2121 +0,0 @@ -#![warn(missing_docs)] -#![crate_name="itertools"] -#![cfg_attr(not(feature = "use_std"), no_std)] - -//! Itertools — extra iterator adaptors, functions and macros. -//! -//! To use the iterator methods in this crate, import the [`Itertools` trait](./trait.Itertools.html): -//! -//! ``` -//! use itertools::Itertools; -//! ``` -//! -//! ## Crate Features -//! -//! - `use_std` -//! - Enabled by default. -//! - Disable to compile itertools using `#![no_std]`. This disables -//! any items that depend on collections (like `group_by`, `unique`, -//! `kmerge`, `join` and many more). -//! -//! ## Rust Version -//! -//! This version of itertools requires Rust 1.12 or later. -//! -#![doc(html_root_url="https://docs.rs/itertools/0.7/")] - -extern crate either; - -#[cfg(not(feature = "use_std"))] -extern crate core as std; - -pub use either::Either; - -#[cfg(feature = "use_std")] -use std::collections::HashMap; -use std::iter::{IntoIterator}; -use std::cmp::Ordering; -use std::fmt; -#[cfg(feature = "use_std")] -use std::hash::Hash; -#[cfg(feature = "use_std")] -use std::fmt::Write; - -#[macro_use] -mod impl_macros; - -// for compatibility with no std and macros -#[doc(hidden)] -pub use std::iter as __std_iter; - -/// The concrete iterator types. -pub mod structs { - pub use adaptors::{ - Dedup, - Interleave, - InterleaveShortest, - Product, - PutBack, - Batching, - Step, - MapResults, - Merge, - MergeBy, - TakeWhileRef, - WhileSome, - Coalesce, - TupleCombinations, - Flatten, - Positions, - Update, - }; - #[cfg(feature = "use_std")] - pub use adaptors::MultiProduct; - #[cfg(feature = "use_std")] - pub use combinations::Combinations; - pub use cons_tuples_impl::ConsTuples; - pub use format::{Format, FormatWith}; - #[cfg(feature = "use_std")] - pub use groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups}; - pub use intersperse::Intersperse; - #[cfg(feature = "use_std")] - pub use kmerge_impl::{KMerge, KMergeBy}; - pub use merge_join::MergeJoinBy; - #[cfg(feature = "use_std")] - pub use multipeek_impl::MultiPeek; - pub use pad_tail::PadUsing; - pub use peeking_take_while::PeekingTakeWhile; - pub use process_results_impl::ProcessResults; - #[cfg(feature = "use_std")] - pub use put_back_n_impl::PutBackN; - #[cfg(feature = "use_std")] - pub use rciter_impl::RcIter; - pub use repeatn::RepeatN; - pub use sources::{RepeatCall, Unfold, Iterate}; - #[cfg(feature = "use_std")] - pub use tee::Tee; - pub use tuple_impl::{TupleBuffer, TupleWindows, Tuples}; - #[cfg(feature = "use_std")] - pub use unique_impl::{Unique, UniqueBy}; - pub use with_position::WithPosition; - pub use zip_eq_impl::ZipEq; - pub use zip_longest::ZipLongest; - pub use ziptuple::Zip; -} -pub use structs::*; -pub use adaptors::flatten; -pub use concat_impl::concat; -pub use cons_tuples_impl::cons_tuples; -pub use diff::diff_with; -pub use diff::Diff; -#[cfg(feature = "use_std")] -pub use kmerge_impl::{kmerge_by}; -pub use minmax::MinMaxResult; -pub use peeking_take_while::PeekingNext; -pub use process_results_impl::process_results; -pub use repeatn::repeat_n; -pub use sources::{repeat_call, unfold, iterate}; -pub use with_position::Position; -pub use ziptuple::multizip; -mod adaptors; -mod either_or_both; -pub use either_or_both::EitherOrBoth; -#[doc(hidden)] -pub mod free; -#[doc(inline)] -pub use free::*; -mod concat_impl; -mod cons_tuples_impl; -#[cfg(feature = "use_std")] -mod combinations; -mod diff; -mod format; -#[cfg(feature = "use_std")] -mod group_map; -#[cfg(feature = "use_std")] -mod groupbylazy; -mod intersperse; -#[cfg(feature = "use_std")] -mod kmerge_impl; -mod merge_join; -mod minmax; -#[cfg(feature = "use_std")] -mod multipeek_impl; -mod pad_tail; -mod peeking_take_while; -mod process_results_impl; -#[cfg(feature = "use_std")] -mod put_back_n_impl; -#[cfg(feature = "use_std")] -mod rciter_impl; -mod repeatn; -mod size_hint; -mod sources; -#[cfg(feature = "use_std")] -mod tee; -mod tuple_impl; -#[cfg(feature = "use_std")] -mod unique_impl; -mod with_position; -mod zip_eq_impl; -mod zip_longest; -mod ziptuple; - -#[macro_export] -/// Create an iterator over the “cartesian product” of iterators. -/// -/// Iterator element type is like `(A, B, ..., E)` if formed -/// from iterators `(I, J, ..., M)` with element types `I::Item = A`, `J::Item = B`, etc. -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { -/// // Iterate over the coordinates of a 4 x 4 x 4 grid -/// // from (0, 0, 0), (0, 0, 1), .., (0, 1, 0), (0, 1, 1), .. etc until (3, 3, 3) -/// for (i, j, k) in iproduct!(0..4, 0..4, 0..4) { -/// // .. -/// } -/// # } -/// ``` -/// -/// **Note:** To enable the macros in this crate, use the `#[macro_use]` -/// attribute when importing the crate: -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { } -/// ``` -macro_rules! iproduct { - (@flatten $I:expr,) => ( - $I - ); - (@flatten $I:expr, $J:expr, $($K:expr,)*) => ( - iproduct!(@flatten $crate::cons_tuples(iproduct!($I, $J)), $($K,)*) - ); - ($I:expr) => ( - $crate::__std_iter::IntoIterator::into_iter($I) - ); - ($I:expr, $J:expr) => ( - $crate::Itertools::cartesian_product(iproduct!($I), iproduct!($J)) - ); - ($I:expr, $J:expr, $($K:expr),+) => ( - iproduct!(@flatten iproduct!($I, $J), $($K,)+) - ); -} - -#[macro_export] -/// Create an iterator running multiple iterators in lockstep. -/// -/// The `izip!` iterator yields elements until any subiterator -/// returns `None`. -/// -/// This is a version of the standard ``.zip()`` that's supporting more than -/// two iterators. The iterator elment type is a tuple with one element -/// from each of the input iterators. Just like ``.zip()``, the iteration stops -/// when the shortest of the inputs reaches its end. -/// -/// **Note:** The result of this macro is an iterator composed of -/// repeated `.zip()` and a `.map()`; it has an anonymous type. -/// Prefer this macro `izip!()` over [`multizip`] for the performance benefits -/// of using the standard library `.zip()`. -/// -/// [`multizip`]: fn.multizip.html -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { -/// -/// // iterate over three sequences side-by-side -/// let mut results = [0, 0, 0, 0]; -/// let inputs = [3, 7, 9, 6]; -/// -/// for (r, index, input) in izip!(&mut results, 0..10, &inputs) { -/// *r = index * 10 + input; -/// } -/// -/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); -/// # } -/// ``` -/// -/// **Note:** To enable the macros in this crate, use the `#[macro_use]` -/// attribute when importing the crate: -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { } -/// ``` -macro_rules! izip { - // @closure creates a tuple-flattening closure for .map() call. usage: - // @closure partial_pattern => partial_tuple , rest , of , iterators - // eg. izip!( @closure ((a, b), c) => (a, b, c) , dd , ee ) - ( @closure $p:pat => $tup:expr ) => { - |$p| $tup - }; - - // The "b" identifier is a different identifier on each recursion level thanks to hygiene. - ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => { - izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*) - }; - - ( $first:expr $( , $rest:expr )* $(,)* ) => { - $crate::__std_iter::IntoIterator::into_iter($first) - $( - .zip($rest) - )* - .map( - izip!(@closure a => (a) $( , $rest )*) - ) - }; -} - -/// The trait `Itertools`: extra iterator adaptors and methods for iterators. -/// -/// This trait defines a number of methods. They are divided into two groups: -/// -/// * *Adaptors* take an iterator and parameter as input, and return -/// a new iterator value. These are listed first in the trait. An example -/// of an adaptor is [`.interleave()`](#method.interleave) -/// -/// * *Regular methods* are those that don't return iterators and instead -/// return a regular value of some other kind. -/// [`.next_tuple()`](#method.next_tuple) is an example and the first regular -/// method in the list. -pub trait Itertools : Iterator { - // adaptors - - /// Alternate elements from two iterators until both have run out. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (1..7).interleave(vec![-1, -2]); - /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]); - /// ``` - fn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter> - where J: IntoIterator<Item = Self::Item>, - Self: Sized - { - interleave(self, other) - } - - /// Alternate elements from two iterators until at least one of them has run - /// out. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (1..7).interleave_shortest(vec![-1, -2]); - /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3]); - /// ``` - fn interleave_shortest<J>(self, other: J) -> InterleaveShortest<Self, J::IntoIter> - where J: IntoIterator<Item = Self::Item>, - Self: Sized - { - adaptors::interleave_shortest(self, other.into_iter()) - } - - /// An iterator adaptor to insert a particular value - /// between each element of the adapted iterator. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// itertools::assert_equal((0..3).intersperse(8), vec![0, 8, 1, 8, 2]); - /// ``` - fn intersperse(self, element: Self::Item) -> Intersperse<Self> - where Self: Sized, - Self::Item: Clone - { - intersperse::intersperse(self, element) - } - - /// Create an iterator which iterates over both this and the specified - /// iterator simultaneously, yielding pairs of two optional elements. - /// - /// This iterator is *fused*. - /// - /// As long as neither input iterator is exhausted yet, it yields two values - /// via `EitherOrBoth::Both`. - /// - /// When the parameter iterator is exhausted, it only yields a value from the - /// `self` iterator via `EitherOrBoth::Left`. - /// - /// When the `self` iterator is exhausted, it only yields a value from the - /// parameter iterator via `EitherOrBoth::Right`. - /// - /// When both iterators return `None`, all further invocations of `.next()` - /// will return `None`. - /// - /// Iterator element type is - /// [`EitherOrBoth<Self::Item, J::Item>`](enum.EitherOrBoth.html). - /// - /// ```rust - /// use itertools::EitherOrBoth::{Both, Right}; - /// use itertools::Itertools; - /// let it = (0..1).zip_longest(1..3); - /// itertools::assert_equal(it, vec![Both(0, 1), Right(2)]); - /// ``` - #[inline] - fn zip_longest<J>(self, other: J) -> ZipLongest<Self, J::IntoIter> - where J: IntoIterator, - Self: Sized - { - zip_longest::zip_longest(self, other.into_iter()) - } - - /// Create an iterator which iterates over both this and the specified - /// iterator simultaneously, yielding pairs of elements. - /// - /// **Panics** if the iterators reach an end and they are not of equal - /// lengths. - #[inline] - fn zip_eq<J>(self, other: J) -> ZipEq<Self, J::IntoIter> - where J: IntoIterator, - Self: Sized - { - zip_eq(self, other) - } - - /// A “meta iterator adaptor”. Its closure recives a reference to the - /// iterator and may pick off as many elements as it likes, to produce the - /// next iterator element. - /// - /// Iterator element type is `B`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // An adaptor that gathers elements in pairs - /// let pit = (0..4).batching(|it| { - /// match it.next() { - /// None => None, - /// Some(x) => match it.next() { - /// None => None, - /// Some(y) => Some((x, y)), - /// } - /// } - /// }); - /// - /// itertools::assert_equal(pit, vec![(0, 1), (2, 3)]); - /// ``` - /// - fn batching<B, F>(self, f: F) -> Batching<Self, F> - where F: FnMut(&mut Self) -> Option<B>, - Self: Sized - { - adaptors::batching(self, f) - } - - /// Return an *iterable* that can group iterator elements. - /// Consecutive elements that map to the same key (“runs”), are assigned - /// to the same group. - /// - /// `GroupBy` is the storage for the lazy grouping operation. - /// - /// If the groups are consumed in order, or if each group's iterator is - /// dropped without keeping it around, then `GroupBy` uses no - /// allocations. It needs allocations only if several group iterators - /// are alive at the same time. - /// - /// This type implements `IntoIterator` (it is **not** an iterator - /// itself), because the group iterators need to borrow from this - /// value. It should be stored in a local variable or temporary and - /// iterated. - /// - /// Iterator element type is `(K, Group)`: the group's key and the - /// group iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // group data into runs of larger than zero or not. - /// let data = vec![1, 3, -2, -2, 1, 0, 1, 2]; - /// // groups: |---->|------>|--------->| - /// - /// // Note: The `&` is significant here, `GroupBy` is iterable - /// // only by reference. You can also call `.into_iter()` explicitly. - /// for (key, group) in &data.into_iter().group_by(|elt| *elt >= 0) { - /// // Check that the sum of each group is +/- 4. - /// assert_eq!(4, group.sum::<i32>().abs()); - /// } - /// ``` - #[cfg(feature = "use_std")] - fn group_by<K, F>(self, key: F) -> GroupBy<K, Self, F> - where Self: Sized, - F: FnMut(&Self::Item) -> K, - K: PartialEq, - { - groupbylazy::new(self, key) - } - - /// Return an *iterable* that can chunk the iterator. - /// - /// Yield subiterators (chunks) that each yield a fixed number elements, - /// determined by `size`. The last chunk will be shorter if there aren't - /// enough elements. - /// - /// `IntoChunks` is based on `GroupBy`: it is iterable (implements - /// `IntoIterator`, **not** `Iterator`), and it only buffers if several - /// chunk iterators are alive at the same time. - /// - /// Iterator element type is `Chunk`, each chunk's iterator. - /// - /// **Panics** if `size` is 0. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1, 1, 2, -2, 6, 0, 3, 1]; - /// //chunk size=3 |------->|-------->|--->| - /// - /// // Note: The `&` is significant here, `IntoChunks` is iterable - /// // only by reference. You can also call `.into_iter()` explicitly. - /// for chunk in &data.into_iter().chunks(3) { - /// // Check that the sum of each chunk is 4. - /// assert_eq!(4, chunk.sum()); - /// } - /// ``` - #[cfg(feature = "use_std")] - fn chunks(self, size: usize) -> IntoChunks<Self> - where Self: Sized, - { - assert!(size != 0); - groupbylazy::new_chunks(self, size) - } - - /// Return an iterator over all contiguous windows producing tuples of - /// a specific size (up to 4). - /// - /// `tuple_windows` clones the iterator elements so that they can be - /// part of successive windows, this makes it most suited for iterators - /// of references and other values that are cheap to copy. - /// - /// ``` - /// use itertools::Itertools; - /// let mut v = Vec::new(); - /// for (a, b) in (1..5).tuple_windows() { - /// v.push((a, b)); - /// } - /// assert_eq!(v, vec![(1, 2), (2, 3), (3, 4)]); - /// - /// let mut it = (1..5).tuple_windows(); - /// assert_eq!(Some((1, 2, 3)), it.next()); - /// assert_eq!(Some((2, 3, 4)), it.next()); - /// assert_eq!(None, it.next()); - /// - /// // this requires a type hint - /// let it = (1..5).tuple_windows::<(_, _, _)>(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); - /// - /// // you can also specify the complete type - /// use itertools::TupleWindows; - /// use std::ops::Range; - /// - /// let it: TupleWindows<Range<u32>, (u32, u32, u32)> = (1..5).tuple_windows(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); - /// ``` - fn tuple_windows<T>(self) -> TupleWindows<Self, T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect, - T::Item: Clone - { - tuple_impl::tuple_windows(self) - } - - /// Return an iterator that groups the items in tuples of a specific size - /// (up to 4). - /// - /// See also the method [`.next_tuple()`](#method.next_tuple). - /// - /// ``` - /// use itertools::Itertools; - /// let mut v = Vec::new(); - /// for (a, b) in (1..5).tuples() { - /// v.push((a, b)); - /// } - /// assert_eq!(v, vec![(1, 2), (3, 4)]); - /// - /// let mut it = (1..7).tuples(); - /// assert_eq!(Some((1, 2, 3)), it.next()); - /// assert_eq!(Some((4, 5, 6)), it.next()); - /// assert_eq!(None, it.next()); - /// - /// // this requires a type hint - /// let it = (1..7).tuples::<(_, _, _)>(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); - /// - /// // you can also specify the complete type - /// use itertools::Tuples; - /// use std::ops::Range; - /// - /// let it: Tuples<Range<u32>, (u32, u32, u32)> = (1..7).tuples(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); - /// ``` - /// - /// See also [`Tuples::into_buffer`](structs/struct.Tuples.html#method.into_buffer). - fn tuples<T>(self) -> Tuples<Self, T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect - { - tuple_impl::tuples(self) - } - - /// Split into an iterator pair that both yield all elements from - /// the original iterator. - /// - /// **Note:** If the iterator is clonable, prefer using that instead - /// of using this method. It is likely to be more efficient. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// let xs = vec![0, 1, 2, 3]; - /// - /// let (mut t1, t2) = xs.into_iter().tee(); - /// itertools::assert_equal(t1.next(), Some(0)); - /// itertools::assert_equal(t2, 0..4); - /// itertools::assert_equal(t1, 1..4); - /// ``` - #[cfg(feature = "use_std")] - fn tee(self) -> (Tee<Self>, Tee<Self>) - where Self: Sized, - Self::Item: Clone - { - tee::new(self) - } - - /// Return an iterator adaptor that steps `n` elements in the base iterator - /// for each iteration. - /// - /// The iterator steps by yielding the next element from the base iterator, - /// then skipping forward `n - 1` elements. - /// - /// Iterator element type is `Self::Item`. - /// - /// **Panics** if the step is 0. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (0..8).step(3); - /// itertools::assert_equal(it, vec![0, 3, 6]); - /// ``` - fn step(self, n: usize) -> Step<Self> - where Self: Sized - { - adaptors::step(self, n) - } - - /// Return an iterator adaptor that applies the provided closure - /// to every `Result::Ok` value. `Result::Err` values are - /// unchanged. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let input = vec![Ok(41), Err(false), Ok(11)]; - /// let it = input.into_iter().map_results(|i| i + 1); - /// itertools::assert_equal(it, vec![Ok(42), Err(false), Ok(12)]); - /// ``` - fn map_results<F, T, U, E>(self, f: F) -> MapResults<Self, F> - where Self: Iterator<Item = Result<T, E>> + Sized, - F: FnMut(T) -> U, - { - adaptors::map_results(self, f) - } - - /// Return an iterator adaptor that merges the two base iterators in - /// ascending order. If both base iterators are sorted (ascending), the - /// result is sorted. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = (0..11).step(3); - /// let b = (0..11).step(5); - /// let it = a.merge(b); - /// itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]); - /// ``` - fn merge<J>(self, other: J) -> Merge<Self, J::IntoIter> - where Self: Sized, - Self::Item: PartialOrd, - J: IntoIterator<Item = Self::Item> - { - merge(self, other) - } - - /// Return an iterator adaptor that merges the two base iterators in order. - /// This is much like `.merge()` but allows for a custom ordering. - /// - /// This can be especially useful for sequences of tuples. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = (0..).zip("bc".chars()); - /// let b = (0..).zip("ad".chars()); - /// let it = a.merge_by(b, |x, y| x.1 <= y.1); - /// itertools::assert_equal(it, vec![(0, 'a'), (0, 'b'), (1, 'c'), (1, 'd')]); - /// ``` - - fn merge_by<J, F>(self, other: J, is_first: F) -> MergeBy<Self, J::IntoIter, F> - where Self: Sized, - J: IntoIterator<Item = Self::Item>, - F: FnMut(&Self::Item, &Self::Item) -> bool - { - adaptors::merge_by_new(self, other.into_iter(), is_first) - } - - /// Create an iterator that merges items from both this and the specified - /// iterator in ascending order. - /// - /// It chooses whether to pair elements based on the `Ordering` returned by the - /// specified compare function. At any point, inspecting the tip of the - /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type - /// `J::Item` respectively, the resulting iterator will: - /// - /// - Emit `EitherOrBoth::Left(i)` when `i < j`, - /// and remove `i` from its source iterator - /// - Emit `EitherOrBoth::Right(j)` when `i > j`, - /// and remove `j` from its source iterator - /// - Emit `EitherOrBoth::Both(i, j)` when `i == j`, - /// and remove both `i` and `j` from their respective source iterators - /// - /// ``` - /// use itertools::Itertools; - /// use itertools::EitherOrBoth::{Left, Right, Both}; - /// - /// let ki = (0..10).step(3); - /// let ku = (0..10).step(5); - /// let ki_ku = ki.merge_join_by(ku, |i, j| i.cmp(j)).map(|either| { - /// match either { - /// Left(_) => "Ki", - /// Right(_) => "Ku", - /// Both(_, _) => "KiKu" - /// } - /// }); - /// - /// itertools::assert_equal(ki_ku, vec!["KiKu", "Ki", "Ku", "Ki", "Ki"]); - /// ``` - #[inline] - fn merge_join_by<J, F>(self, other: J, cmp_fn: F) -> MergeJoinBy<Self, J::IntoIter, F> - where J: IntoIterator, - F: FnMut(&Self::Item, &J::Item) -> std::cmp::Ordering, - Self: Sized - { - merge_join_by(self, other, cmp_fn) - } - - - /// Return an iterator adaptor that flattens an iterator of iterators by - /// merging them in ascending order. - /// - /// If all base iterators are sorted (ascending), the result is sorted. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = (0..6).step(3); - /// let b = (1..6).step(3); - /// let c = (2..6).step(3); - /// let it = vec![a, b, c].into_iter().kmerge(); - /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]); - /// ``` - #[cfg(feature = "use_std")] - fn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter> - where Self: Sized, - Self::Item: IntoIterator, - <Self::Item as IntoIterator>::Item: PartialOrd, - { - kmerge(self) - } - - /// Return an iterator adaptor that flattens an iterator of iterators by - /// merging them according to the given closure. - /// - /// The closure `first` is called with two elements *a*, *b* and should - /// return `true` if *a* is ordered before *b*. - /// - /// If all base iterators are sorted according to `first`, the result is - /// sorted. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = vec![-1f64, 2., 3., -5., 6., -7.]; - /// let b = vec![0., 2., -4.]; - /// let mut it = vec![a, b].into_iter().kmerge_by(|a, b| a.abs() < b.abs()); - /// assert_eq!(it.next(), Some(0.)); - /// assert_eq!(it.last(), Some(-7.)); - /// ``` - #[cfg(feature = "use_std")] - fn kmerge_by<F>(self, first: F) - -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F> - where Self: Sized, - Self::Item: IntoIterator, - F: FnMut(&<Self::Item as IntoIterator>::Item, - &<Self::Item as IntoIterator>::Item) -> bool - { - kmerge_by(self, first) - } - - /// Return an iterator adaptor that iterates over the cartesian product of - /// the element sets of two iterators `self` and `J`. - /// - /// Iterator element type is `(Self::Item, J::Item)`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (0..2).cartesian_product("αβ".chars()); - /// itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]); - /// ``` - fn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoIter> - where Self: Sized, - Self::Item: Clone, - J: IntoIterator, - J::IntoIter: Clone - { - adaptors::cartesian_product(self, other.into_iter()) - } - - /// Return an iterator adaptor that iterates over the cartesian product of - /// all subiterators returned by meta-iterator `self`. - /// - /// All provided iterators must yield the same `Item` type. To generate - /// the product of iterators yielding multiple types, use the - /// [`iproduct`](macro.iproduct.html) macro instead. - /// - /// - /// The iterator element type is `Vec<T>`, where `T` is the iterator element - /// of the subiterators. - /// - /// ``` - /// use itertools::Itertools; - /// let mut multi_prod = (0..3).map(|i| (i * 2)..(i * 2 + 2)) - /// .multi_cartesian_product(); - /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 5])); - /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 5])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 5])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 5])); - /// assert_eq!(multi_prod.next(), None); - /// ``` - #[cfg(feature = "use_std")] - fn multi_cartesian_product(self) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter> - where Self: Iterator + Sized, - Self::Item: IntoIterator, - <Self::Item as IntoIterator>::IntoIter: Clone, - <Self::Item as IntoIterator>::Item: Clone - { - adaptors::multi_cartesian_product(self) - } - - /// Return an iterator adaptor that uses the passed-in closure to - /// optionally merge together consecutive elements. - /// - /// The closure `f` is passed two elements, `previous` and `current` and may - /// return either (1) `Ok(combined)` to merge the two values or - /// (2) `Err((previous', current'))` to indicate they can't be merged. - /// In (2), the value `previous'` is emitted by the iterator. - /// Either (1) `combined` or (2) `current'` becomes the previous value - /// when coalesce continues with the next pair of elements to merge. The - /// value that remains at the end is also emitted by the iterator. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sum same-sign runs together - /// let data = vec![-1., -2., -3., 3., 1., 0., -1.]; - /// itertools::assert_equal(data.into_iter().coalesce(|x, y| - /// if (x >= 0.) == (y >= 0.) { - /// Ok(x + y) - /// } else { - /// Err((x, y)) - /// }), - /// vec![-6., 4., -1.]); - /// ``` - fn coalesce<F>(self, f: F) -> Coalesce<Self, F> - where Self: Sized, - F: FnMut(Self::Item, Self::Item) - -> Result<Self::Item, (Self::Item, Self::Item)> - { - adaptors::coalesce(self, f) - } - - /// Remove duplicates from sections of consecutive identical elements. - /// If the iterator is sorted, all elements will be unique. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1., 1., 2., 3., 3., 2., 2.]; - /// itertools::assert_equal(data.into_iter().dedup(), - /// vec![1., 2., 3., 2.]); - /// ``` - fn dedup(self) -> Dedup<Self> - where Self: Sized, - Self::Item: PartialEq, - { - adaptors::dedup(self) - } - - /// Return an iterator adaptor that filters out elements that have - /// already been produced once during the iteration. Duplicates - /// are detected using hash and equality. - /// - /// Clones of visited elements are stored in a hash set in the - /// iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![10, 20, 30, 20, 40, 10, 50]; - /// itertools::assert_equal(data.into_iter().unique(), - /// vec![10, 20, 30, 40, 50]); - /// ``` - #[cfg(feature = "use_std")] - fn unique(self) -> Unique<Self> - where Self: Sized, - Self::Item: Clone + Eq + Hash - { - unique_impl::unique(self) - } - - /// Return an iterator adaptor that filters out elements that have - /// already been produced once during the iteration. - /// - /// Duplicates are detected by comparing the key they map to - /// with the keying function `f` by hash and equality. - /// The keys are stored in a hash set in the iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec!["a", "bb", "aa", "c", "ccc"]; - /// itertools::assert_equal(data.into_iter().unique_by(|s| s.len()), - /// vec!["a", "bb", "ccc"]); - /// ``` - #[cfg(feature = "use_std")] - fn unique_by<V, F>(self, f: F) -> UniqueBy<Self, V, F> - where Self: Sized, - V: Eq + Hash, - F: FnMut(&Self::Item) -> V - { - unique_impl::unique_by(self, f) - } - - /// Return an iterator adaptor that borrows from this iterator and - /// takes items while the closure `accept` returns `true`. - /// - /// This adaptor can only be used on iterators that implement `PeekingNext` - /// like `.peekable()`, `put_back` and a few other collection iterators. - /// - /// The last and rejected element (first `false`) is still available when - /// `peeking_take_while` is done. - /// - /// - /// See also [`.take_while_ref()`](#method.take_while_ref) - /// which is a similar adaptor. - fn peeking_take_while<F>(&mut self, accept: F) -> PeekingTakeWhile<Self, F> - where Self: Sized + PeekingNext, - F: FnMut(&Self::Item) -> bool, - { - peeking_take_while::peeking_take_while(self, accept) - } - - /// Return an iterator adaptor that borrows from a `Clone`-able iterator - /// to only pick off elements while the predicate `accept` returns `true`. - /// - /// It uses the `Clone` trait to restore the original iterator so that the - /// last and rejected element (first `false`) is still available when - /// `take_while_ref` is done. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut hexadecimals = "0123456789abcdef".chars(); - /// - /// let decimals = hexadecimals.take_while_ref(|c| c.is_numeric()) - /// .collect::<String>(); - /// assert_eq!(decimals, "0123456789"); - /// assert_eq!(hexadecimals.next(), Some('a')); - /// - /// ``` - fn take_while_ref<F>(&mut self, accept: F) -> TakeWhileRef<Self, F> - where Self: Clone, - F: FnMut(&Self::Item) -> bool - { - adaptors::take_while_ref(self, accept) - } - - /// Return an iterator adaptor that filters `Option<A>` iterator elements - /// and produces `A`. Stops on the first `None` encountered. - /// - /// Iterator element type is `A`, the unwrapped element. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // List all hexadecimal digits - /// itertools::assert_equal( - /// (0..).map(|i| std::char::from_digit(i, 16)).while_some(), - /// "0123456789abcdef".chars()); - /// - /// ``` - fn while_some<A>(self) -> WhileSome<Self> - where Self: Sized + Iterator<Item = Option<A>> - { - adaptors::while_some(self) - } - - /// Return an iterator adaptor that iterates over the combinations of the - /// elements from an iterator. - /// - /// Iterator element can be any homogeneous tuple of type `Self::Item` with - /// size up to 4. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut v = Vec::new(); - /// for (a, b) in (1..5).tuple_combinations() { - /// v.push((a, b)); - /// } - /// assert_eq!(v, vec![(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]); - /// - /// let mut it = (1..5).tuple_combinations(); - /// assert_eq!(Some((1, 2, 3)), it.next()); - /// assert_eq!(Some((1, 2, 4)), it.next()); - /// assert_eq!(Some((1, 3, 4)), it.next()); - /// assert_eq!(Some((2, 3, 4)), it.next()); - /// assert_eq!(None, it.next()); - /// - /// // this requires a type hint - /// let it = (1..5).tuple_combinations::<(_, _, _)>(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); - /// - /// // you can also specify the complete type - /// use itertools::TupleCombinations; - /// use std::ops::Range; - /// - /// let it: TupleCombinations<Range<u32>, (u32, u32, u32)> = (1..5).tuple_combinations(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); - /// ``` - fn tuple_combinations<T>(self) -> TupleCombinations<Self, T> - where Self: Sized + Clone, - Self::Item: Clone, - T: adaptors::HasCombination<Self>, - { - adaptors::tuple_combinations(self) - } - - /// Return an iterator adaptor that iterates over the `n`-length combinations of - /// the elements from an iterator. - /// - /// Iterator element type is `Vec<Self::Item>`. The iterator produces a new Vec per iteration, - /// and clones the iterator elements. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (1..5).combinations(3); - /// itertools::assert_equal(it, vec![ - /// vec![1, 2, 3], - /// vec![1, 2, 4], - /// vec![1, 3, 4], - /// vec![2, 3, 4], - /// ]); - /// ``` - #[cfg(feature = "use_std")] - fn combinations(self, n: usize) -> Combinations<Self> - where Self: Sized, - Self::Item: Clone - { - combinations::combinations(self, n) - } - - /// Return an iterator adaptor that pads the sequence to a minimum length of - /// `min` by filling missing elements using a closure `f`. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (0..5).pad_using(10, |i| 2*i); - /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 10, 12, 14, 16, 18]); - /// - /// let it = (0..10).pad_using(5, |i| 2*i); - /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - /// - /// let it = (0..5).pad_using(10, |i| 2*i).rev(); - /// itertools::assert_equal(it, vec![18, 16, 14, 12, 10, 4, 3, 2, 1, 0]); - /// ``` - fn pad_using<F>(self, min: usize, f: F) -> PadUsing<Self, F> - where Self: Sized, - F: FnMut(usize) -> Self::Item - { - pad_tail::pad_using(self, min, f) - } - - /// Flatten an iterator of iterables into a single combined sequence of all - /// the elements in the iterables. - /// - /// This is more or less equivalent to `.flat_map` with an identity - /// function. - /// - /// See also the [`flatten`](fn.flatten.html) function. - /// - /// ```ignore - /// use itertools::Itertools; - /// - /// let data = vec![vec![1, 2, 3], vec![4, 5, 6]]; - /// let flattened = data.iter().flatten(); - /// - /// itertools::assert_equal(flattened, &[1, 2, 3, 4, 5, 6]); - /// ``` - fn flatten(self) -> Flatten<Self, <Self::Item as IntoIterator>::IntoIter> - where Self: Sized, - Self::Item: IntoIterator - { - adaptors::flatten(self) - } - - /// Return an iterator adaptor that wraps each element in a `Position` to - /// ease special-case handling of the first or last elements. - /// - /// Iterator element type is - /// [`Position<Self::Item>`](enum.Position.html) - /// - /// ``` - /// use itertools::{Itertools, Position}; - /// - /// let it = (0..4).with_position(); - /// itertools::assert_equal(it, - /// vec![Position::First(0), - /// Position::Middle(1), - /// Position::Middle(2), - /// Position::Last(3)]); - /// - /// let it = (0..1).with_position(); - /// itertools::assert_equal(it, vec![Position::Only(0)]); - /// ``` - fn with_position(self) -> WithPosition<Self> - where Self: Sized, - { - with_position::with_position(self) - } - - /// Return an iterator adaptor that yields the indices of all elements - /// satisfying a predicate, counted from the start of the iterator. - /// - /// Equivalent to `iter.enumerate().filter(|(_, v)| predicate(v)).map(|(i, _)| i)`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1, 2, 3, 3, 4, 6, 7, 9]; - /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 0), vec![1, 4, 5]); - /// - /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 1).rev(), vec![7, 6, 3, 2, 0]); - /// ``` - fn positions<P>(self, predicate: P) -> Positions<Self, P> - where Self: Sized, - P: FnMut(Self::Item) -> bool, - { - adaptors::positions(self, predicate) - } - - /// Return an iterator adaptor that applies a mutating function - /// to each element before yielding it. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let input = vec![vec![1], vec![3, 2, 1]]; - /// let it = input.into_iter().update(|mut v| v.push(0)); - /// itertools::assert_equal(it, vec![vec![1, 0], vec![3, 2, 1, 0]]); - /// ``` - fn update<F>(self, updater: F) -> Update<Self, F> - where Self: Sized, - F: FnMut(&mut Self::Item), - { - adaptors::update(self, updater) - } - - // non-adaptor methods - /// Advances the iterator and returns the next items grouped in a tuple of - /// a specific size (up to 4). - /// - /// If there are enough elements to be grouped in a tuple, then the tuple is - /// returned inside `Some`, otherwise `None` is returned. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut iter = 1..5; - /// - /// assert_eq!(Some((1, 2)), iter.next_tuple()); - /// ``` - fn next_tuple<T>(&mut self) -> Option<T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect - { - T::collect_from_iter_no_buf(self) - } - - /// Collects all items from the iterator into a tuple of a specific size - /// (up to 4). - /// - /// If the number of elements inside the iterator is **exactly** equal to - /// the tuple size, then the tuple is returned inside `Some`, otherwise - /// `None` is returned. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let iter = 1..3; - /// - /// if let Some((x, y)) = iter.collect_tuple() { - /// assert_eq!((x, y), (1, 2)) - /// } else { - /// panic!("Expected two elements") - /// } - /// ``` - fn collect_tuple<T>(mut self) -> Option<T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect - { - match self.next_tuple() { - elt @ Some(_) => match self.next() { - Some(_) => None, - None => elt, - }, - _ => None - } - } - - - /// Find the position and value of the first element satisfying a predicate. - /// - /// The iterator is not advanced past the first element found. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let text = "Hα"; - /// assert_eq!(text.chars().find_position(|ch| ch.is_lowercase()), Some((1, 'α'))); - /// ``` - fn find_position<P>(&mut self, mut pred: P) -> Option<(usize, Self::Item)> - where P: FnMut(&Self::Item) -> bool - { - let mut index = 0usize; - for elt in self { - if pred(&elt) { - return Some((index, elt)); - } - index += 1; - } - None - } - - /// Check whether all elements compare equal. - /// - /// Empty iterators are considered to have equal elements: - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; - /// assert!(!data.iter().all_equal()); - /// assert!(data[0..3].iter().all_equal()); - /// assert!(data[3..5].iter().all_equal()); - /// assert!(data[5..8].iter().all_equal()); - /// - /// let data : Option<usize> = None; - /// assert!(data.into_iter().all_equal()); - /// ``` - fn all_equal(&mut self) -> bool - where Self::Item: PartialEq, - { - self.dedup().nth(1).is_none() - } - - /// Consume the first `n` elements from the iterator eagerly, - /// and return the same iterator again. - /// - /// It works similarly to *.skip(* `n` *)* except it is eager and - /// preserves the iterator type. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut iter = "αβγ".chars().dropping(2); - /// itertools::assert_equal(iter, "γ".chars()); - /// ``` - /// - /// *Fusing notes: if the iterator is exhausted by dropping, - /// the result of calling `.next()` again depends on the iterator implementation.* - fn dropping(mut self, n: usize) -> Self - where Self: Sized - { - if n > 0 { - self.nth(n - 1); - } - self - } - - /// Consume the last `n` elements from the iterator eagerly, - /// and return the same iterator again. - /// - /// This is only possible on double ended iterators. `n` may be - /// larger than the number of elements. - /// - /// Note: This method is eager, dropping the back elements immediately and - /// preserves the iterator type. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let init = vec![0, 3, 6, 9].into_iter().dropping_back(1); - /// itertools::assert_equal(init, vec![0, 3, 6]); - /// ``` - fn dropping_back(mut self, n: usize) -> Self - where Self: Sized, - Self: DoubleEndedIterator - { - if n > 0 { - (&mut self).rev().nth(n - 1); - } - self - } - - /// Run the closure `f` eagerly on each element of the iterator. - /// - /// Consumes the iterator until its end. - /// - /// ``` - /// use std::sync::mpsc::channel; - /// use itertools::Itertools; - /// - /// let (tx, rx) = channel(); - /// - /// // use .foreach() to apply a function to each value -- sending it - /// (0..5).map(|x| x * 2 + 1).foreach(|x| { tx.send(x).unwrap(); } ); - /// - /// drop(tx); - /// - /// itertools::assert_equal(rx.iter(), vec![1, 3, 5, 7, 9]); - /// ``` - fn foreach<F>(self, mut f: F) - where F: FnMut(Self::Item), - Self: Sized, - { - self.fold((), move |(), element| f(element)) - } - - /// Combine all an iterator's elements into one element by using `Extend`. - /// - /// This combinator will extend the first item with each of the rest of the - /// items of the iterator. If the iterator is empty, the default value of - /// `I::Item` is returned. - /// - /// ```rust - /// use itertools::Itertools; - /// - /// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; - /// assert_eq!(input.into_iter().concat(), - /// vec![1, 2, 3, 4, 5, 6]); - /// ``` - fn concat(self) -> Self::Item - where Self: Sized, - Self::Item: Extend<<<Self as Iterator>::Item as IntoIterator>::Item> + IntoIterator + Default - { - concat(self) - } - - /// `.collect_vec()` is simply a type specialization of `.collect()`, - /// for convenience. - #[cfg(feature = "use_std")] - fn collect_vec(self) -> Vec<Self::Item> - where Self: Sized - { - self.collect() - } - - /// Assign to each reference in `self` from the `from` iterator, - /// stopping at the shortest of the two iterators. - /// - /// The `from` iterator is queried for its next element before the `self` - /// iterator, and if either is exhausted the method is done. - /// - /// Return the number of elements written. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut xs = [0; 4]; - /// xs.iter_mut().set_from(1..); - /// assert_eq!(xs, [1, 2, 3, 4]); - /// ``` - #[inline] - fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize - where Self: Iterator<Item = &'a mut A>, - J: IntoIterator<Item = A> - { - let mut count = 0; - for elt in from { - match self.next() { - None => break, - Some(ptr) => *ptr = elt, - } - count += 1; - } - count - } - - /// Combine all iterator elements into one String, seperated by `sep`. - /// - /// Use the `Display` implementation of each element. - /// - /// ``` - /// use itertools::Itertools; - /// - /// assert_eq!(["a", "b", "c"].iter().join(", "), "a, b, c"); - /// assert_eq!([1, 2, 3].iter().join(", "), "1, 2, 3"); - /// ``` - #[cfg(feature = "use_std")] - fn join(&mut self, sep: &str) -> String - where Self::Item: std::fmt::Display - { - match self.next() { - None => String::new(), - Some(first_elt) => { - // estimate lower bound of capacity needed - let (lower, _) = self.size_hint(); - let mut result = String::with_capacity(sep.len() * lower); - write!(&mut result, "{}", first_elt).unwrap(); - for elt in self { - result.push_str(sep); - write!(&mut result, "{}", elt).unwrap(); - } - result - } - } - } - - /// Format all iterator elements, separated by `sep`. - /// - /// All elements are formatted (any formatting trait) - /// with `sep` inserted between each element. - /// - /// **Panics** if the formatter helper is formatted more than once. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = [1.1, 2.71828, -3.]; - /// assert_eq!( - /// format!("{:.2}", data.iter().format(", ")), - /// "1.10, 2.72, -3.00"); - /// ``` - fn format(self, sep: &str) -> Format<Self> - where Self: Sized, - { - format::new_format_default(self, sep) - } - - /// Format all iterator elements, separated by `sep`. - /// - /// This is a customizable version of `.format()`. - /// - /// The supplied closure `format` is called once per iterator element, - /// with two arguments: the element and a callback that takes a - /// `&Display` value, i.e. any reference to type that implements `Display`. - /// - /// Using `&format_args!(...)` is the most versatile way to apply custom - /// element formatting. The callback can be called multiple times if needed. - /// - /// **Panics** if the formatter helper is formatted more than once. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = [1.1, 2.71828, -3.]; - /// let data_formatter = data.iter().format_with(", ", |elt, f| f(&format_args!("{:.2}", elt))); - /// assert_eq!(format!("{}", data_formatter), - /// "1.10, 2.72, -3.00"); - /// - /// // .format_with() is recursively composable - /// let matrix = [[1., 2., 3.], - /// [4., 5., 6.]]; - /// let matrix_formatter = matrix.iter().format_with("\n", |row, f| { - /// f(&row.iter().format_with(", ", |elt, g| g(&elt))) - /// }); - /// assert_eq!(format!("{}", matrix_formatter), - /// "1, 2, 3\n4, 5, 6"); - /// - /// - /// ``` - fn format_with<F>(self, sep: &str, format: F) -> FormatWith<Self, F> - where Self: Sized, - F: FnMut(Self::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result, - { - format::new_format(self, sep, format) - } - - /// Fold `Result` values from an iterator. - /// - /// Only `Ok` values are folded. If no error is encountered, the folded - /// value is returned inside `Ok`. Otherwise, the operation terminates - /// and returns the first `Err` value it encounters. No iterator elements are - /// consumed after the first error. - /// - /// The first accumulator value is the `start` parameter. - /// Each iteration passes the accumulator value and the next value inside `Ok` - /// to the fold function `f` and its return value becomes the new accumulator value. - /// - /// For example the sequence *Ok(1), Ok(2), Ok(3)* will result in a - /// computation like this: - /// - /// ```ignore - /// let mut accum = start; - /// accum = f(accum, 1); - /// accum = f(accum, 2); - /// accum = f(accum, 3); - /// ``` - /// - /// With a `start` value of 0 and an addition as folding function, - /// this effetively results in *((0 + 1) + 2) + 3* - /// - /// ``` - /// use std::ops::Add; - /// use itertools::Itertools; - /// - /// let values = [1, 2, -2, -1, 2, 1]; - /// assert_eq!( - /// values.iter() - /// .map(Ok::<_, ()>) - /// .fold_results(0, Add::add), - /// Ok(3) - /// ); - /// assert!( - /// values.iter() - /// .map(|&x| if x >= 0 { Ok(x) } else { Err("Negative number") }) - /// .fold_results(0, Add::add) - /// .is_err() - /// ); - /// ``` - fn fold_results<A, E, B, F>(&mut self, mut start: B, mut f: F) -> Result<B, E> - where Self: Iterator<Item = Result<A, E>>, - F: FnMut(B, A) -> B - { - for elt in self { - match elt { - Ok(v) => start = f(start, v), - Err(u) => return Err(u), - } - } - Ok(start) - } - - /// Fold `Option` values from an iterator. - /// - /// Only `Some` values are folded. If no `None` is encountered, the folded - /// value is returned inside `Some`. Otherwise, the operation terminates - /// and returns `None`. No iterator elements are consumed after the `None`. - /// - /// This is the `Option` equivalent to `fold_results`. - /// - /// ``` - /// use std::ops::Add; - /// use itertools::Itertools; - /// - /// let mut values = vec![Some(1), Some(2), Some(-2)].into_iter(); - /// assert_eq!(values.fold_options(5, Add::add), Some(5 + 1 + 2 - 2)); - /// - /// let mut more_values = vec![Some(2), None, Some(0)].into_iter(); - /// assert!(more_values.fold_options(0, Add::add).is_none()); - /// assert_eq!(more_values.next().unwrap(), Some(0)); - /// ``` - fn fold_options<A, B, F>(&mut self, mut start: B, mut f: F) -> Option<B> - where Self: Iterator<Item = Option<A>>, - F: FnMut(B, A) -> B - { - for elt in self { - match elt { - Some(v) => start = f(start, v), - None => return None, - } - } - Some(start) - } - - /// Accumulator of the elements in the iterator. - /// - /// Like `.fold()`, without a base case. If the iterator is - /// empty, return `None`. With just one element, return it. - /// Otherwise elements are accumulated in sequence using the closure `f`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// assert_eq!((0..10).fold1(|x, y| x + y).unwrap_or(0), 45); - /// assert_eq!((0..0).fold1(|x, y| x * y), None); - /// ``` - fn fold1<F>(mut self, f: F) -> Option<Self::Item> - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, - { - self.next().map(move |x| self.fold(x, f)) - } - - /// Accumulate the elements in the iterator in a tree-like manner. - /// - /// You can think of it as, while there's more than one item, repeatedly - /// combining adjacent items. It does so in bottom-up-merge-sort order, - /// however, so that it needs only logarithmic stack space. - /// - /// This produces a call tree like the following (where the calls under - /// an item are done after reading that item): - /// - /// ```text - /// 1 2 3 4 5 6 7 - /// │ │ │ │ │ │ │ - /// └─f └─f └─f │ - /// │ │ │ │ - /// └───f └─f - /// │ │ - /// └─────f - /// ``` - /// - /// Which, for non-associative functions, will typically produce a different - /// result than the linear call tree used by `fold1`: - /// - /// ```text - /// 1 2 3 4 5 6 7 - /// │ │ │ │ │ │ │ - /// └─f─f─f─f─f─f - /// ``` - /// - /// If `f` is associative, prefer the normal `fold1` instead. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // The same tree as above - /// let num_strings = (1..8).map(|x| x.to_string()); - /// assert_eq!(num_strings.tree_fold1(|x, y| format!("f({}, {})", x, y)), - /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); - /// - /// // Like fold1, an empty iterator produces None - /// assert_eq!((0..0).tree_fold1(|x, y| x * y), None); - /// - /// // tree_fold1 matches fold1 for associative operations... - /// assert_eq!((0..10).tree_fold1(|x, y| x + y), - /// (0..10).fold1(|x, y| x + y)); - /// // ...but not for non-associative ones - /// assert!((0..10).tree_fold1(|x, y| x - y) - /// != (0..10).fold1(|x, y| x - y)); - /// ``` - // FIXME: If minver changes to >= 1.13, use `assert_ne!` in the doctest. - fn tree_fold1<F>(mut self, mut f: F) -> Option<Self::Item> - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, - { - type State<T> = Result<T, Option<T>>; - - fn inner0<T, II, FF>(it: &mut II, f: &mut FF) -> State<T> - where - II: Iterator<Item = T>, - FF: FnMut(T, T) -> T - { - // This function could be replaced with `it.next().ok_or(None)`, - // but half the useful tree_fold1 work is combining adjacent items, - // so put that in a form that LLVM is more likely to optimize well. - - let a = - if let Some(v) = it.next() { v } - else { return Err(None) }; - let b = - if let Some(v) = it.next() { v } - else { return Err(Some(a)) }; - Ok(f(a, b)) - } - - fn inner<T, II, FF>(stop: usize, it: &mut II, f: &mut FF) -> State<T> - where - II: Iterator<Item = T>, - FF: FnMut(T, T) -> T - { - let mut x = try!(inner0(it, f)); - for height in 0..stop { - // Try to get another tree the same size with which to combine it, - // creating a new tree that's twice as big for next time around. - let next = - if height == 0 { - inner0(it, f) - } else { - inner(height, it, f) - }; - match next { - Ok(y) => x = f(x, y), - - // If we ran out of items, combine whatever we did manage - // to get. It's better combined with the current value - // than something in a parent frame, because the tree in - // the parent is always as least as big as this one. - Err(None) => return Err(Some(x)), - Err(Some(y)) => return Err(Some(f(x, y))), - } - } - Ok(x) - } - - match inner(usize::max_value(), &mut self, &mut f) { - Err(x) => x, - _ => unreachable!(), - } - } - - /// An iterator method that applies a function, producing a single, final value. - /// - /// `fold_while()` is basically equivalent to `fold()` but with additional support for - /// early exit via short-circuiting. - /// - /// ``` - /// use itertools::Itertools; - /// use itertools::FoldWhile::{Continue, Done}; - /// - /// let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - /// - /// let mut result = 0; - /// - /// // for loop: - /// for i in &numbers { - /// if *i > 5 { - /// break; - /// } - /// result = result + i; - /// } - /// - /// // fold: - /// let result2 = numbers.iter().fold(0, |acc, x| { - /// if *x > 5 { acc } else { acc + x } - /// }); - /// - /// // fold_while: - /// let result3 = numbers.iter().fold_while(0, |acc, x| { - /// if *x > 5 { Done(acc) } else { Continue(acc + x) } - /// }).into_inner(); - /// - /// // they're the same - /// assert_eq!(result, result2); - /// assert_eq!(result2, result3); - /// ``` - /// - /// The big difference between the computations of `result2` and `result3` is that while - /// `fold()` called the provided closure for every item of the callee iterator, - /// `fold_while()` actually stopped iterating as soon as it encountered `Fold::Done(_)`. - fn fold_while<B, F>(&mut self, init: B, mut f: F) -> FoldWhile<B> - where Self: Sized, - F: FnMut(B, Self::Item) -> FoldWhile<B> - { - let mut acc = init; - while let Some(item) = self.next() { - match f(acc, item) { - FoldWhile::Continue(res) => acc = res, - res @ FoldWhile::Done(_) => return res, - } - } - FoldWhile::Continue(acc) - } - - /// Collect all iterator elements into a sorted vector in ascending order. - /// - /// **Note:** This consumes the entire iterator, uses the - /// `slice::sort_by()` method and returns the sorted vector. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sort the letters of the text in ascending order - /// let text = "bdacfe"; - /// itertools::assert_equal(text.chars().sorted(), - /// "abcdef".chars()); - /// ``` - #[cfg(feature = "use_std")] - fn sorted(self) -> Vec<Self::Item> - where Self: Sized, - Self::Item: Ord - { - self.sorted_by(Ord::cmp) - } - - /// Collect all iterator elements into a sorted vector. - /// - /// **Note:** This consumes the entire iterator, uses the - /// `slice::sort_by()` method and returns the sorted vector. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; - /// - /// let oldest_people_first = people - /// .into_iter() - /// .sorted_by(|a, b| Ord::cmp(&b.1, &a.1)) - /// .into_iter() - /// .map(|(person, _age)| person); - /// - /// itertools::assert_equal(oldest_people_first, - /// vec!["Jill", "Jack", "Jane", "John"]); - /// ``` - #[cfg(feature = "use_std")] - fn sorted_by<F>(self, cmp: F) -> Vec<Self::Item> - where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - let mut v: Vec<Self::Item> = self.collect(); - - v.sort_by(cmp); - v - } - - /// Collect all iterator elements into a sorted vector. - /// - /// **Note:** This consumes the entire iterator, uses the - /// `slice::sort_by_key()` method and returns the sorted vector. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; - /// - /// let oldest_people_first = people - /// .into_iter() - /// .sorted_by_key(|x| -x.1) - /// .into_iter() - /// .map(|(person, _age)| person); - /// - /// itertools::assert_equal(oldest_people_first, - /// vec!["Jill", "Jack", "Jane", "John"]); - /// ``` - #[cfg(feature = "use_std")] - fn sorted_by_key<K, F>(self, f: F) -> Vec<Self::Item> - where Self: Sized, - K: Ord, - F: FnMut(&Self::Item) -> K, - { - let mut v: Vec<Self::Item> = self.collect(); - - v.sort_by_key(f); - v - } - - /// Collect all iterator elements into one of two - /// partitions. Unlike `Iterator::partition`, each partition may - /// have a distinct type. - /// - /// ``` - /// use itertools::{Itertools, Either}; - /// - /// let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)]; - /// - /// let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures - /// .into_iter() - /// .partition_map(|r| { - /// match r { - /// Ok(v) => Either::Left(v), - /// Err(v) => Either::Right(v), - /// } - /// }); - /// - /// assert_eq!(successes, [1, 2]); - /// assert_eq!(failures, [false, true]); - /// ``` - fn partition_map<A, B, F, L, R>(self, predicate: F) -> (A, B) - where Self: Sized, - F: Fn(Self::Item) -> Either<L, R>, - A: Default + Extend<L>, - B: Default + Extend<R>, - { - let mut left = A::default(); - let mut right = B::default(); - - for val in self { - match predicate(val) { - Either::Left(v) => left.extend(Some(v)), - Either::Right(v) => right.extend(Some(v)), - } - } - - (left, right) - } - - /// Return a `HashMap` of keys mapped to `Vec`s of values. Keys and values - /// are taken from `(Key, Value)` tuple pairs yielded by the input iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)]; - /// let lookup = data.into_iter().into_group_map(); - /// - /// assert_eq!(lookup[&0], vec![10, 20]); - /// assert_eq!(lookup.get(&1), None); - /// assert_eq!(lookup[&2], vec![12, 42]); - /// assert_eq!(lookup[&3], vec![13, 33]); - /// ``` - #[cfg(feature = "use_std")] - fn into_group_map<K, V>(self) -> HashMap<K, Vec<V>> - where Self: Iterator<Item=(K, V)> + Sized, - K: Hash + Eq, - { - group_map::into_group_map(self) - } - - /// Return the minimum and maximum elements in the iterator. - /// - /// The return type `MinMaxResult` is an enum of three variants: - /// - /// - `NoElements` if the iterator is empty. - /// - `OneElement(x)` if the iterator has exactly one element. - /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two - /// values are equal if and only if there is more than one - /// element in the iterator and all elements are equal. - /// - /// On an iterator of length `n`, `minmax` does `1.5 * n` comparisons, - /// and so is faster than calling `min` and `max` separately which does - /// `2 * n` comparisons. - /// - /// # Examples - /// - /// ``` - /// use itertools::Itertools; - /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; - /// - /// let a: [i32; 0] = []; - /// assert_eq!(a.iter().minmax(), NoElements); - /// - /// let a = [1]; - /// assert_eq!(a.iter().minmax(), OneElement(&1)); - /// - /// let a = [1, 2, 3, 4, 5]; - /// assert_eq!(a.iter().minmax(), MinMax(&1, &5)); - /// - /// let a = [1, 1, 1, 1]; - /// assert_eq!(a.iter().minmax(), MinMax(&1, &1)); - /// ``` - /// - /// The elements can be floats but no particular result is guaranteed - /// if an element is NaN. - fn minmax(self) -> MinMaxResult<Self::Item> - where Self: Sized, Self::Item: PartialOrd - { - minmax::minmax_impl(self, |_| (), |x, y, _, _| x < y) - } - - /// Return the minimum and maximum element of an iterator, as determined by - /// the specified function. - /// - /// The return value is a variant of `MinMaxResult` like for `minmax()`. - /// - /// For the minimum, the first minimal element is returned. For the maximum, - /// the last maximal element wins. This matches the behavior of the standard - /// `Iterator::min()` and `Iterator::max()` methods. - /// - /// The keys can be floats but no particular result is guaranteed - /// if a key is NaN. - fn minmax_by_key<K, F>(self, key: F) -> MinMaxResult<Self::Item> - where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K - { - minmax::minmax_impl(self, key, |_, _, xk, yk| xk < yk) - } - - /// Return the minimum and maximum element of an iterator, as determined by - /// the specified comparison function. - /// - /// The return value is a variant of `MinMaxResult` like for `minmax()`. - /// - /// For the minimum, the first minimal element is returned. For the maximum, - /// the last maximal element wins. This matches the behavior of the standard - /// `Iterator::min()` and `Iterator::max()` methods. - fn minmax_by<F>(self, mut compare: F) -> MinMaxResult<Self::Item> - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering - { - minmax::minmax_impl( - self, - |_| (), - |x, y, _, _| Ordering::Less == compare(x, y) - ) - } -} - -impl<T: ?Sized> Itertools for T where T: Iterator { } - -/// Return `true` if both iterables produce equal sequences -/// (elements pairwise equal and sequences of the same length), -/// `false` otherwise. -/// -/// This is an `IntoIterator` enabled function that is similar to the standard -/// library method `Iterator::eq`. -/// -/// ``` -/// assert!(itertools::equal(vec![1, 2, 3], 1..4)); -/// assert!(!itertools::equal(&[0, 0], &[0, 0, 0])); -/// ``` -pub fn equal<I, J>(a: I, b: J) -> bool - where I: IntoIterator, - J: IntoIterator, - I::Item: PartialEq<J::Item> -{ - let mut ia = a.into_iter(); - let mut ib = b.into_iter(); - loop { - match ia.next() { - Some(x) => match ib.next() { - Some(y) => if x != y { return false; }, - None => return false, - }, - None => return ib.next().is_none() - } - } -} - -/// Assert that two iterables produce equal sequences, with the same -/// semantics as *equal(a, b)*. -/// -/// **Panics** on assertion failure with a message that shows the -/// two iteration elements. -/// -/// ```ignore -/// assert_equal("exceed".split('c'), "excess".split('c')); -/// // ^PANIC: panicked at 'Failed assertion Some("eed") == Some("ess") for iteration 1', -/// ``` -pub fn assert_equal<I, J>(a: I, b: J) - where I: IntoIterator, - J: IntoIterator, - I::Item: fmt::Debug + PartialEq<J::Item>, - J::Item: fmt::Debug, -{ - let mut ia = a.into_iter(); - let mut ib = b.into_iter(); - let mut i = 0; - loop { - match (ia.next(), ib.next()) { - (None, None) => return, - (a, b) => { - let equal = match (&a, &b) { - (&Some(ref a), &Some(ref b)) => a == b, - _ => false, - }; - assert!(equal, "Failed assertion {a:?} == {b:?} for iteration {i}", - i=i, a=a, b=b); - i += 1; - } - } - } -} - -/// Partition a sequence using predicate `pred` so that elements -/// that map to `true` are placed before elements which map to `false`. -/// -/// The order within the partitions is arbitrary. -/// -/// Return the index of the split point. -/// -/// ``` -/// use itertools::partition; -/// -/// # // use repeated numbers to not promise any ordering -/// let mut data = [7, 1, 1, 7, 1, 1, 7]; -/// let split_index = partition(&mut data, |elt| *elt >= 3); -/// -/// assert_eq!(data, [7, 7, 7, 1, 1, 1, 1]); -/// assert_eq!(split_index, 3); -/// ``` -pub fn partition<'a, A: 'a, I, F>(iter: I, mut pred: F) -> usize - where I: IntoIterator<Item = &'a mut A>, - I::IntoIter: DoubleEndedIterator, - F: FnMut(&A) -> bool -{ - let mut split_index = 0; - let mut iter = iter.into_iter(); - 'main: while let Some(front) = iter.next() { - if !pred(front) { - loop { - match iter.next_back() { - Some(back) => if pred(back) { - std::mem::swap(front, back); - break; - }, - None => break 'main, - } - } - } - split_index += 1; - } - split_index -} - -/// An enum used for controlling the execution of `.fold_while()`. -/// -/// See [`.fold_while()`](trait.Itertools.html#method.fold_while) for more information. -#[derive(Copy, Clone, Debug)] -pub enum FoldWhile<T> { - /// Continue folding with this value - Continue(T), - /// Fold is complete and will return this value - Done(T), -} - -impl<T> FoldWhile<T> { - /// Return the value in the continue or done. - pub fn into_inner(self) -> T { - match self { - FoldWhile::Continue(x) | FoldWhile::Done(x) => x, - } - } - - /// Return true if `self` is `Done`, false if it is `Continue`. - pub fn is_done(&self) -> bool { - match *self { - FoldWhile::Continue(_) => false, - FoldWhile::Done(_) => true, - } - } -} diff --git a/vendor/itertools-0.7.8/src/merge_join.rs b/vendor/itertools-0.7.8/src/merge_join.rs deleted file mode 100644 index 5f9a0f4013..0000000000 --- a/vendor/itertools-0.7.8/src/merge_join.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::cmp::Ordering; -use std::iter::Fuse; -use std::fmt; - -use super::adaptors::{PutBack, put_back}; -use either_or_both::EitherOrBoth; - -/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. -/// -/// See [`.merge_join_by()`](trait.Itertools.html#method.merge_join_by) for more information. -pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F) - -> MergeJoinBy<I::IntoIter, J::IntoIter, F> - where I: IntoIterator, - J: IntoIterator, - F: FnMut(&I::Item, &J::Item) -> Ordering -{ - MergeJoinBy { - left: put_back(left.into_iter().fuse()), - right: put_back(right.into_iter().fuse()), - cmp_fn: cmp_fn - } -} - -/// An iterator adaptor that merge-joins items from the two base iterators in ascending order. -/// -/// See [`.merge_join_by()`](../trait.Itertools.html#method.merge_join_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MergeJoinBy<I: Iterator, J: Iterator, F> { - left: PutBack<Fuse<I>>, - right: PutBack<Fuse<J>>, - cmp_fn: F -} - -impl<I, J, F> fmt::Debug for MergeJoinBy<I, J, F> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, - J: Iterator + fmt::Debug, - J::Item: fmt::Debug, -{ - debug_fmt_fields!(MergeJoinBy, left, right); -} - -impl<I, J, F> Iterator for MergeJoinBy<I, J, F> - where I: Iterator, - J: Iterator, - F: FnMut(&I::Item, &J::Item) -> Ordering -{ - type Item = EitherOrBoth<I::Item, J::Item>; - - fn next(&mut self) -> Option<Self::Item> { - match (self.left.next(), self.right.next()) { - (None, None) => None, - (Some(left), None) => - Some(EitherOrBoth::Left(left)), - (None, Some(right)) => - Some(EitherOrBoth::Right(right)), - (Some(left), Some(right)) => { - match (self.cmp_fn)(&left, &right) { - Ordering::Equal => - Some(EitherOrBoth::Both(left, right)), - Ordering::Less => { - self.right.put_back(right); - Some(EitherOrBoth::Left(left)) - }, - Ordering::Greater => { - self.left.put_back(left); - Some(EitherOrBoth::Right(right)) - } - } - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (a_lower, a_upper) = self.left.size_hint(); - let (b_lower, b_upper) = self.right.size_hint(); - - let lower = ::std::cmp::max(a_lower, b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => Some(x + y), - _ => None, - }; - - (lower, upper) - } -} diff --git a/vendor/itertools-0.7.8/src/minmax.rs b/vendor/itertools-0.7.8/src/minmax.rs deleted file mode 100644 index 38180ef6d0..0000000000 --- a/vendor/itertools-0.7.8/src/minmax.rs +++ /dev/null @@ -1,114 +0,0 @@ - -/// `MinMaxResult` is an enum returned by `minmax`. See `Itertools::minmax()` for -/// more detail. -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum MinMaxResult<T> { - /// Empty iterator - NoElements, - - /// Iterator with one element, so the minimum and maximum are the same - OneElement(T), - - /// More than one element in the iterator, the first element is not larger - /// than the second - MinMax(T, T) -} - -impl<T: Clone> MinMaxResult<T> { - /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option` - /// has variant `None` if and only if the `MinMaxResult` has variant - /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`. - /// If the `MinMaxResult` has variant `OneElement(x)`, performing this - /// operation will make one clone of `x`. - /// - /// # Examples - /// - /// ``` - /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax}; - /// - /// let r: MinMaxResult<i32> = NoElements; - /// assert_eq!(r.into_option(), None); - /// - /// let r = OneElement(1); - /// assert_eq!(r.into_option(), Some((1, 1))); - /// - /// let r = MinMax(1, 2); - /// assert_eq!(r.into_option(), Some((1, 2))); - /// ``` - pub fn into_option(self) -> Option<(T,T)> { - match self { - MinMaxResult::NoElements => None, - MinMaxResult::OneElement(x) => Some((x.clone(), x)), - MinMaxResult::MinMax(x, y) => Some((x, y)) - } - } -} - -/// Implementation guts for `minmax` and `minmax_by_key`. -pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F, - mut lt: L) -> MinMaxResult<I::Item> - where I: Iterator, - F: FnMut(&I::Item) -> K, - L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, -{ - let (mut min, mut max, mut min_key, mut max_key) = match it.next() { - None => return MinMaxResult::NoElements, - Some(x) => { - match it.next() { - None => return MinMaxResult::OneElement(x), - Some(y) => { - let xk = key_for(&x); - let yk = key_for(&y); - if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)} - } - } - } - }; - - loop { - // `first` and `second` are the two next elements we want to look - // at. We first compare `first` and `second` (#1). The smaller one - // is then compared to current minimum (#2). The larger one is - // compared to current maximum (#3). This way we do 3 comparisons - // for 2 elements. - let first = match it.next() { - None => break, - Some(x) => x - }; - let second = match it.next() { - None => { - let first_key = key_for(&first); - if lt(&first, &min, &first_key, &min_key) { - min = first; - } else if !lt(&first, &max, &first_key, &max_key) { - max = first; - } - break; - } - Some(x) => x - }; - let first_key = key_for(&first); - let second_key = key_for(&second); - if !lt(&second, &first, &second_key, &first_key) { - if lt(&first, &min, &first_key, &min_key) { - min = first; - min_key = first_key; - } - if !lt(&second, &max, &second_key, &max_key) { - max = second; - max_key = second_key; - } - } else { - if lt(&second, &min, &second_key, &min_key) { - min = second; - min_key = second_key; - } - if !lt(&first, &max, &first_key, &max_key) { - max = first; - max_key = first_key; - } - } - } - - MinMaxResult::MinMax(min, max) -} diff --git a/vendor/itertools-0.7.8/src/multipeek_impl.rs b/vendor/itertools-0.7.8/src/multipeek_impl.rs deleted file mode 100644 index a6a2fb33eb..0000000000 --- a/vendor/itertools-0.7.8/src/multipeek_impl.rs +++ /dev/null @@ -1,104 +0,0 @@ - - -use std::iter::Fuse; -use std::collections::VecDeque; -use size_hint; -use PeekingNext; - -/// See [`multipeek()`](../fn.multipeek.html) for more information. -#[derive(Clone, Debug)] -pub struct MultiPeek<I> - where I: Iterator -{ - iter: Fuse<I>, - buf: VecDeque<I::Item>, - index: usize, -} - -/// An iterator adaptor that allows the user to peek at multiple `.next()` -/// values without advancing the base iterator. -pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter> - where I: IntoIterator -{ - MultiPeek { - iter: iterable.into_iter().fuse(), - buf: VecDeque::new(), - index: 0, - } -} - -impl<I> MultiPeek<I> - where I: Iterator -{ - /// Reset the peeking “cursor” - pub fn reset_peek(&mut self) { - self.index = 0; - } -} - -impl<I: Iterator> MultiPeek<I> { - /// Works exactly like `.next()` with the only difference that it doesn't - /// advance itself. `.peek()` can be called multiple times, to peek - /// further ahead. - pub fn peek(&mut self) -> Option<&I::Item> { - let ret = if self.index < self.buf.len() { - Some(&self.buf[self.index]) - } else { - match self.iter.next() { - Some(x) => { - self.buf.push_back(x); - Some(&self.buf[self.index]) - } - None => return None, - } - }; - - self.index += 1; - ret - } -} - -impl<I> PeekingNext for MultiPeek<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if self.buf.is_empty() { - if let Some(r) = self.peek() { - if !accept(r) { return None } - } - } else { - if let Some(r) = self.buf.get(0) { - if !accept(r) { return None } - } - } - self.next() - } -} - -impl<I> Iterator for MultiPeek<I> - where I: Iterator -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - self.index = 0; - if self.buf.is_empty() { - self.iter.next() - } else { - self.buf.pop_front() - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) - } -} - -// Same size -impl<I> ExactSizeIterator for MultiPeek<I> - where I: ExactSizeIterator -{} - - diff --git a/vendor/itertools-0.7.8/src/pad_tail.rs b/vendor/itertools-0.7.8/src/pad_tail.rs deleted file mode 100644 index c9cfe6af30..0000000000 --- a/vendor/itertools-0.7.8/src/pad_tail.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::iter::Fuse; -use size_hint; - -/// An iterator adaptor that pads a sequence to a minimum length by filling -/// missing elements using a closure. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.pad_using()`](../trait.Itertools.html#method.pad_using) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct PadUsing<I, F> { - iter: Fuse<I>, - min: usize, - pos: usize, - filler: F, -} - -/// Create a new **PadUsing** iterator. -pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F> - where I: Iterator, - F: FnMut(usize) -> I::Item -{ - PadUsing { - iter: iter.fuse(), - min: min, - pos: 0, - filler: filler, - } -} - -impl<I, F> Iterator for PadUsing<I, F> - where I: Iterator, - F: FnMut(usize) -> I::Item -{ - type Item = I::Item; - - #[inline] - fn next(&mut self) -> Option<I::Item> { - match self.iter.next() { - None => { - if self.pos < self.min { - let e = Some((self.filler)(self.pos)); - self.pos += 1; - e - } else { - None - } - }, - e => { - self.pos += 1; - e - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let tail = self.min.saturating_sub(self.pos); - size_hint::max(self.iter.size_hint(), (tail, Some(tail))) - } -} - -impl<I, F> DoubleEndedIterator for PadUsing<I, F> - where I: DoubleEndedIterator + ExactSizeIterator, - F: FnMut(usize) -> I::Item -{ - fn next_back(&mut self) -> Option<I::Item> { - if self.min == 0 { - self.iter.next_back() - } else if self.iter.len() >= self.min { - self.min -= 1; - self.iter.next_back() - } else { - self.min -= 1; - Some((self.filler)(self.min)) - } - } -} - -impl<I, F> ExactSizeIterator for PadUsing<I, F> - where I: ExactSizeIterator, - F: FnMut(usize) -> I::Item -{} diff --git a/vendor/itertools-0.7.8/src/peeking_take_while.rs b/vendor/itertools-0.7.8/src/peeking_take_while.rs deleted file mode 100644 index 0b2291dfdd..0000000000 --- a/vendor/itertools-0.7.8/src/peeking_take_while.rs +++ /dev/null @@ -1,149 +0,0 @@ - -use std::iter::Peekable; -use PutBack; -#[cfg(feature = "use_std")] -use PutBackN; - -/// An iterator that allows peeking at an element before deciding to accept it. -/// -/// See [`.peeking_take_while()`](trait.Itertools.html#method.peeking_take_while) -/// for more information. -/// -/// This is implemented by peeking adaptors like peekable and put back, -/// but also by a few iterators that can be peeked natively, like the slice’s -/// by reference iterator (`std::slice::Iter`). -pub trait PeekingNext : Iterator { - /// Pass a reference to the next iterator element to the closure `accept`; - /// if `accept` returns true, return it as the next element, - /// else None. - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool; -} - -impl<I> PeekingNext for Peekable<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if let Some(r) = self.peek() { - if !accept(r) { - return None; - } - } - self.next() - } -} - -impl<I> PeekingNext for PutBack<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if let Some(r) = self.next() { - if !accept(&r) { - self.put_back(r); - return None; - } - Some(r) - } else { - None - } - } -} - -#[cfg(feature = "use_std")] -impl<I> PeekingNext for PutBackN<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if let Some(r) = self.next() { - if !accept(&r) { - self.put_back(r); - return None; - } - Some(r) - } else { - None - } - } -} - -/// An iterator adaptor that takes items while a closure returns `true`. -/// -/// See [`.peeking_take_while()`](../trait.Itertools.html#method.peeking_take_while) -/// for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct PeekingTakeWhile<'a, I: 'a, F> - where I: Iterator, -{ - iter: &'a mut I, - f: F, -} - -/// Create a PeekingTakeWhile -pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F> - where I: Iterator, -{ - PeekingTakeWhile { - iter: iter, - f: f, - } -} - -impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F> - where I: PeekingNext, - F: FnMut(&I::Item) -> bool, - -{ - type Item = I::Item; - fn next(&mut self) -> Option<Self::Item> { - self.iter.peeking_next(&mut self.f) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, hi) = self.iter.size_hint(); - (0, hi) - } -} - -// Some iterators are so lightweight we can simply clone them to save their -// state and use that for peeking. -macro_rules! peeking_next_by_clone { - ([$($typarm:tt)*] $type_:ty) => { - impl<$($typarm)*> PeekingNext for $type_ { - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - let saved_state = self.clone(); - if let Some(r) = self.next() { - if !accept(&r) { - *self = saved_state; - } else { - return Some(r) - } - } - None - } - } - } -} - -peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> } -peeking_next_by_clone! { ['a] ::std::str::Chars<'a> } -peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> } -peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> } -peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> } -peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> } -peeking_next_by_clone! { [T] ::std::iter::Empty<T> } -#[cfg(feature = "use_std")] -peeking_next_by_clone! { ['a, T] ::std::collections::linked_list::Iter<'a, T> } -#[cfg(feature = "use_std")] -peeking_next_by_clone! { ['a, T] ::std::collections::vec_deque::Iter<'a, T> } - -// cloning a Rev has no extra overhead; peekable and put backs are never DEI. -peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator] - ::std::iter::Rev<I> } diff --git a/vendor/itertools-0.7.8/src/process_results_impl.rs b/vendor/itertools-0.7.8/src/process_results_impl.rs deleted file mode 100644 index f78515d77f..0000000000 --- a/vendor/itertools-0.7.8/src/process_results_impl.rs +++ /dev/null @@ -1,81 +0,0 @@ - -/// An iterator that produces only the `T` values as long as the -/// inner iterator produces `Ok(T)`. -/// -/// Used by [`process_results`](../fn.process_results.html), see its docs -/// for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct ProcessResults<'a, I, E: 'a> { - error: &'a mut Result<(), E>, - iter: I, -} - -impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> - where I: Iterator<Item = Result<T, E>> -{ - type Item = T; - - fn next(&mut self) -> Option<Self::Item> { - match self.iter.next() { - Some(Ok(x)) => Some(x), - Some(Err(e)) => { - *self.error = Err(e); - None - } - None => None, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, hi) = self.iter.size_hint(); - (0, hi) - } -} - -/// “Lift” a function of the values of an iterator so that it can process -/// an iterator of `Result` values instead. -/// -/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where -/// `T` is the value type and `E` the error type. -/// -/// `processor` is a closure that receives an adapted version of the iterable -/// as the only argument — the adapted iterator produces elements of type `T`, -/// as long as the original iterator produces `Ok` values. -/// -/// If the original iterable produces an error at any point, the adapted -/// iterator ends and the `process_results` function will return the -/// error iself. -/// -/// Otherwise, the return value from the closure is returned wrapped -/// inside `Ok`. -/// -/// # Example -/// -/// ``` -/// use itertools::process_results; -/// -/// type R = Result<i32, &'static str>; -/// -/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)]; -/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")]; -/// -/// // “Lift” the iterator .max() method to work on the values in Results using process_results -/// -/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0)); -/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0)); -/// -/// assert_eq!(first_max, Ok(3)); -/// assert!(second_max.is_err()); -/// ``` -pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E> - where I: IntoIterator<Item = Result<T, E>>, - F: FnOnce(ProcessResults<I::IntoIter, E>) -> R -{ - let iter = iterable.into_iter(); - let mut error = Ok(()); - - let result = processor(ProcessResults { error: &mut error, iter: iter }); - - error.map(|_| result) -} diff --git a/vendor/itertools-0.7.8/src/put_back_n_impl.rs b/vendor/itertools-0.7.8/src/put_back_n_impl.rs deleted file mode 100644 index cc08320714..0000000000 --- a/vendor/itertools-0.7.8/src/put_back_n_impl.rs +++ /dev/null @@ -1,63 +0,0 @@ -use size_hint; - -/// An iterator adaptor that allows putting multiple -/// items in front of the iterator. -/// -/// Iterator element type is `I::Item`. -#[derive(Debug, Clone)] -pub struct PutBackN<I: Iterator> { - top: Vec<I::Item>, - iter: I, -} - -/// Create an iterator where you can put back multiple values to the front -/// of the iteration. -/// -/// Iterator element type is `I::Item`. -pub fn put_back_n<I>(iterable: I) -> PutBackN<I::IntoIter> - where I: IntoIterator -{ - PutBackN { - top: Vec::new(), - iter: iterable.into_iter(), - } -} - -impl<I: Iterator> PutBackN<I> { - /// Puts x in front of the iterator. - /// The values are yielded in order of the most recently put back - /// values first. - /// - /// ```rust - /// use itertools::put_back_n; - /// - /// let mut it = put_back_n(1..5); - /// it.next(); - /// it.put_back(1); - /// it.put_back(0); - /// - /// assert!(itertools::equal(it, 0..5)); - /// ``` - #[inline] - pub fn put_back(&mut self, x: I::Item) { - self.top.push(x); - } -} - -impl<I: Iterator> Iterator for PutBackN<I> { - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - if self.top.is_empty() { - self.iter.next() - } else { - self.top.pop() - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add_scalar(self.iter.size_hint(), self.top.len()) - } -} - diff --git a/vendor/itertools-0.7.8/src/rciter_impl.rs b/vendor/itertools-0.7.8/src/rciter_impl.rs deleted file mode 100644 index 1c3b03b5bc..0000000000 --- a/vendor/itertools-0.7.8/src/rciter_impl.rs +++ /dev/null @@ -1,98 +0,0 @@ - -use std::iter::IntoIterator; -use std::rc::Rc; -use std::cell::RefCell; - -/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait. -#[derive(Debug)] -pub struct RcIter<I> { - /// The boxed iterator. - pub rciter: Rc<RefCell<I>>, -} - -/// Return an iterator inside a `Rc<RefCell<_>>` wrapper. -/// -/// The returned `RcIter` can be cloned, and each clone will refer back to the -/// same original iterator. -/// -/// `RcIter` allows doing interesting things like using `.zip()` on an iterator with -/// itself, at the cost of runtime borrow checking which may have a performance -/// penalty. -/// -/// Iterator element type is `Self::Item`. -/// -/// ``` -/// use itertools::rciter; -/// use itertools::zip; -/// -/// // In this example a range iterator is created and we iterate it using -/// // three separate handles (two of them given to zip). -/// // We also use the IntoIterator implementation for `&RcIter`. -/// -/// let mut iter = rciter(0..9); -/// let mut z = zip(&iter, &iter); -/// -/// assert_eq!(z.next(), Some((0, 1))); -/// assert_eq!(z.next(), Some((2, 3))); -/// assert_eq!(z.next(), Some((4, 5))); -/// assert_eq!(iter.next(), Some(6)); -/// assert_eq!(z.next(), Some((7, 8))); -/// assert_eq!(z.next(), None); -/// ``` -/// -/// **Panics** in iterator methods if a borrow error is encountered in the -/// iterator methods. It can only happen if the `RcIter` is reentered in -/// `.next()`, i.e. if it somehow participates in an “iterator knot” -/// where it is an adaptor of itself. -pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter> - where I: IntoIterator -{ - RcIter { rciter: Rc::new(RefCell::new(iterable.into_iter())) } -} - -impl<I> Clone for RcIter<I> { - #[inline] - fn clone(&self) -> RcIter<I> { - RcIter { rciter: self.rciter.clone() } - } -} - -impl<A, I> Iterator for RcIter<I> - where I: Iterator<Item = A> -{ - type Item = A; - #[inline] - fn next(&mut self) -> Option<A> { - self.rciter.borrow_mut().next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // To work sanely with other API that assume they own an iterator, - // so it can't change in other places, we can't guarantee as much - // in our size_hint. Other clones may drain values under our feet. - let (_, hi) = self.rciter.borrow().size_hint(); - (0, hi) - } -} - -impl<I> DoubleEndedIterator for RcIter<I> - where I: DoubleEndedIterator -{ - #[inline] - fn next_back(&mut self) -> Option<I::Item> { - self.rciter.borrow_mut().next_back() - } -} - -/// Return an iterator from `&RcIter<I>` (by simply cloning it). -impl<'a, I> IntoIterator for &'a RcIter<I> - where I: Iterator -{ - type Item = I::Item; - type IntoIter = RcIter<I>; - - fn into_iter(self) -> RcIter<I> { - self.clone() - } -} diff --git a/vendor/itertools-0.7.8/src/repeatn.rs b/vendor/itertools-0.7.8/src/repeatn.rs deleted file mode 100644 index 1c7c310014..0000000000 --- a/vendor/itertools-0.7.8/src/repeatn.rs +++ /dev/null @@ -1,54 +0,0 @@ - -/// An iterator that produces *n* repetitions of an element. -/// -/// See [`repeat_n()`](../fn.repeat_n.html) for more information. -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct RepeatN<A> { - elt: Option<A>, - n: usize, -} - -/// Create an iterator that produces `n` repetitions of `element`. -pub fn repeat_n<A>(element: A, n: usize) -> RepeatN<A> - where A: Clone, -{ - if n == 0 { - RepeatN { elt: None, n: n, } - } else { - RepeatN { elt: Some(element), n: n, } - } -} - -impl<A> Iterator for RepeatN<A> - where A: Clone -{ - type Item = A; - - fn next(&mut self) -> Option<Self::Item> { - if self.n > 1 { - self.n -= 1; - self.elt.as_ref().cloned() - } else { - self.n = 0; - self.elt.take() - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.n, Some(self.n)) - } -} - -impl<A> DoubleEndedIterator for RepeatN<A> - where A: Clone -{ - #[inline] - fn next_back(&mut self) -> Option<Self::Item> { - self.next() - } -} - -impl<A> ExactSizeIterator for RepeatN<A> - where A: Clone -{} diff --git a/vendor/itertools-0.7.8/src/size_hint.rs b/vendor/itertools-0.7.8/src/size_hint.rs deleted file mode 100644 index be54443f29..0000000000 --- a/vendor/itertools-0.7.8/src/size_hint.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! Arithmetic on **Iterator** *.size_hint()* values. -//! - -use std::usize; -use std::cmp; - -/// **SizeHint** is the return type of **Iterator::size_hint()**. -pub type SizeHint = (usize, Option<usize>); - -/// Add **SizeHint** correctly. -#[inline] -pub fn add(a: SizeHint, b: SizeHint) -> SizeHint { - let min = a.0.checked_add(b.0).unwrap_or(usize::MAX); - let max = match (a.1, b.1) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None, - }; - - (min, max) -} - -/// Add **x** correctly to a **SizeHint**. -#[inline] -pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint { - let (mut low, mut hi) = sh; - low = low.saturating_add(x); - hi = hi.and_then(|elt| elt.checked_add(x)); - (low, hi) -} - -/// Sbb **x** correctly to a **SizeHint**. -#[inline] -#[allow(dead_code)] -pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint { - let (mut low, mut hi) = sh; - low = low.saturating_sub(x); - hi = hi.map(|elt| elt.saturating_sub(x)); - (low, hi) -} - - -/// Multiply **SizeHint** correctly -/// -/// ```ignore -/// use std::usize; -/// use itertools::size_hint; -/// -/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))), -/// (9, Some(16))); -/// -/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)), -/// (usize::MAX, None)); -/// -/// assert_eq!(size_hint::mul((3, None), (0, Some(0))), -/// (0, Some(0))); -/// ``` -#[inline] -pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint { - let low = a.0.checked_mul(b.0).unwrap_or(usize::MAX); - let hi = match (a.1, b.1) { - (Some(x), Some(y)) => x.checked_mul(y), - (Some(0), None) | (None, Some(0)) => Some(0), - _ => None, - }; - (low, hi) -} - -/// Multiply **x** correctly with a **SizeHint**. -#[inline] -pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint { - let (mut low, mut hi) = sh; - low = low.saturating_mul(x); - hi = hi.and_then(|elt| elt.checked_mul(x)); - (low, hi) -} - -/// Return the maximum -#[inline] -pub fn max(a: SizeHint, b: SizeHint) -> SizeHint { - let (a_lower, a_upper) = a; - let (b_lower, b_upper) = b; - - let lower = cmp::max(a_lower, b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => Some(cmp::max(x, y)), - _ => None, - }; - - (lower, upper) -} - -/// Return the minimum -#[inline] -pub fn min(a: SizeHint, b: SizeHint) -> SizeHint { - let (a_lower, a_upper) = a; - let (b_lower, b_upper) = b; - let lower = cmp::min(a_lower, b_lower); - let upper = match (a_upper, b_upper) { - (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)), - _ => a_upper.or(b_upper), - }; - (lower, upper) -} diff --git a/vendor/itertools-0.7.8/src/sources.rs b/vendor/itertools-0.7.8/src/sources.rs deleted file mode 100644 index 562801bf00..0000000000 --- a/vendor/itertools-0.7.8/src/sources.rs +++ /dev/null @@ -1,187 +0,0 @@ -//! Iterators that are sources (produce elements from parameters, -//! not from another iterator). - -use std::fmt; -use std::mem; - -/// See [`repeat_call`](../fn.repeat_call.html) for more information. -pub struct RepeatCall<F> { - f: F, -} - -impl<F> fmt::Debug for RepeatCall<F> -{ - debug_fmt_fields!(RepeatCall, ); -} - -/// An iterator source that produces elements indefinitely by calling -/// a given closure. -/// -/// Iterator element type is the return type of the closure. -/// -/// ``` -/// use itertools::repeat_call; -/// use itertools::Itertools; -/// use std::collections::BinaryHeap; -/// -/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]); -/// -/// // extract each element in sorted order -/// for element in repeat_call(|| heap.pop()).while_some() { -/// print!("{}", element); -/// } -/// -/// itertools::assert_equal( -/// repeat_call(|| 1).take(5), -/// vec![1, 1, 1, 1, 1] -/// ); -/// ``` -pub fn repeat_call<F, A>(function: F) -> RepeatCall<F> - where F: FnMut() -> A -{ - RepeatCall { f: function } -} - -impl<A, F> Iterator for RepeatCall<F> - where F: FnMut() -> A -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option<A> { - Some((self.f)()) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (usize::max_value(), None) - } -} - -/// Creates a new unfold source with the specified closure as the "iterator -/// function" and an initial state to eventually pass to the closure -/// -/// `unfold` is a general iterator builder: it has a mutable state value, -/// and a closure with access to the state that produces the next value. -/// -/// This more or less equivalent to a regular struct with an `Iterator` -/// implementation, and is useful for one-off iterators. -/// -/// ``` -/// // an iterator that yields sequential Fibonacci numbers, -/// // and stops at the maximum representable value. -/// -/// use itertools::unfold; -/// -/// let (mut x1, mut x2) = (1u32, 1u32); -/// let mut fibonacci = unfold((), move |_| { -/// // Attempt to get the next Fibonacci number -/// let next = x1.saturating_add(x2); -/// -/// // Shift left: ret <- x1 <- x2 <- next -/// let ret = x1; -/// x1 = x2; -/// x2 = next; -/// -/// // If addition has saturated at the maximum, we are finished -/// if ret == x1 && ret > 1 { -/// return None; -/// } -/// -/// Some(ret) -/// }); -/// -/// itertools::assert_equal(fibonacci.by_ref().take(8), -/// vec![1, 1, 2, 3, 5, 8, 13, 21]); -/// assert_eq!(fibonacci.last(), Some(2_971_215_073)) -/// ``` -pub fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F> - where F: FnMut(&mut St) -> Option<A> -{ - Unfold { - f: f, - state: initial_state, - } -} - -impl<St, F> fmt::Debug for Unfold<St, F> - where St: fmt::Debug, -{ - debug_fmt_fields!(Unfold, state); -} - -/// See [`unfold`](../fn.unfold.html) for more information. -#[derive(Clone)] -#[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct Unfold<St, F> { - f: F, - /// Internal state that will be passed to the closure on the next iteration - pub state: St, -} - -impl<A, St, F> Iterator for Unfold<St, F> - where F: FnMut(&mut St) -> Option<A> -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option<A> { - (self.f)(&mut self.state) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // no possible known bounds at this point - (0, None) - } -} - -/// An iterator that infinitely applies function to value and yields results. -/// -/// This `struct` is created by the [`iterate()`] function. See its documentation for more. -/// -/// [`iterate()`]: ../fn.iterate.html -#[derive(Clone)] -#[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct Iterate<St, F> { - state: St, - f: F, -} - -impl<St, F> fmt::Debug for Iterate<St, F> - where St: fmt::Debug, -{ - debug_fmt_fields!(Iterate, state); -} - -impl<St, F> Iterator for Iterate<St, F> - where F: FnMut(&St) -> St -{ - type Item = St; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - let next_state = (self.f)(&self.state); - Some(mem::replace(&mut self.state, next_state)) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - (usize::max_value(), None) - } -} - -/// Creates a new iterator that infinitely applies function to value and yields results. -/// -/// ``` -/// use itertools::iterate; -/// -/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]); -/// ``` -pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F> - where F: FnMut(&St) -> St -{ - Iterate { - state: initial_value, - f: f, - } -} diff --git a/vendor/itertools-0.7.8/src/tee.rs b/vendor/itertools-0.7.8/src/tee.rs deleted file mode 100644 index 77d261759d..0000000000 --- a/vendor/itertools-0.7.8/src/tee.rs +++ /dev/null @@ -1,78 +0,0 @@ -use super::size_hint; - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; - -/// Common buffer object for the two tee halves -#[derive(Debug)] -struct TeeBuffer<A, I> { - backlog: VecDeque<A>, - iter: I, - /// The owner field indicates which id should read from the backlog - owner: bool, -} - -/// One half of an iterator pair where both return the same elements. -/// -/// See [`.tee()`](../trait.Itertools.html#method.tee) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct Tee<I> - where I: Iterator -{ - rcbuffer: Rc<RefCell<TeeBuffer<I::Item, I>>>, - id: bool, -} - -pub fn new<I>(iter: I) -> (Tee<I>, Tee<I>) - where I: Iterator -{ - let buffer = TeeBuffer{backlog: VecDeque::new(), iter: iter, owner: false}; - let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true}; - let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false}; - (t1, t2) -} - -impl<I> Iterator for Tee<I> - where I: Iterator, - I::Item: Clone -{ - type Item = I::Item; - fn next(&mut self) -> Option<I::Item> { - // .borrow_mut may fail here -- but only if the user has tied some kind of weird - // knot where the iterator refers back to itself. - let mut buffer = self.rcbuffer.borrow_mut(); - if buffer.owner == self.id { - match buffer.backlog.pop_front() { - None => {} - some_elt => return some_elt, - } - } - match buffer.iter.next() { - None => None, - Some(elt) => { - buffer.backlog.push_back(elt.clone()); - buffer.owner = !self.id; - Some(elt) - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let buffer = self.rcbuffer.borrow(); - let sh = buffer.iter.size_hint(); - - if buffer.owner == self.id { - let log_len = buffer.backlog.len(); - size_hint::add_scalar(sh, log_len) - } else { - sh - } - } -} - -impl<I> ExactSizeIterator for Tee<I> - where I: ExactSizeIterator, - I::Item: Clone -{} diff --git a/vendor/itertools-0.7.8/src/tuple_impl.rs b/vendor/itertools-0.7.8/src/tuple_impl.rs deleted file mode 100644 index 0daa7800c1..0000000000 --- a/vendor/itertools-0.7.8/src/tuple_impl.rs +++ /dev/null @@ -1,266 +0,0 @@ -//! Some iterator that produces tuples - -use std::iter::Fuse; - -/// An iterator over a incomplete tuple. -/// -/// See [`.tuples()`](../trait.Itertools.html#method.tuples) and -/// [`Tuples::into_buffer()`](struct.Tuples.html#method.into_buffer). -#[derive(Debug)] -pub struct TupleBuffer<T> - where T: TupleCollect -{ - cur: usize, - buf: T::Buffer, -} - -impl<T> TupleBuffer<T> - where T: TupleCollect -{ - fn new(buf: T::Buffer) -> Self { - TupleBuffer { - cur: 0, - buf: buf, - } - } -} - -impl<T> Iterator for TupleBuffer<T> - where T: TupleCollect -{ - type Item = T::Item; - - fn next(&mut self) -> Option<Self::Item> { - let s = self.buf.as_mut(); - if let Some(ref mut item) = s.get_mut(self.cur) { - self.cur += 1; - item.take() - } else { - None - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let buffer = &self.buf.as_ref()[self.cur..]; - let len = if buffer.len() == 0 { - 0 - } else { - buffer.iter() - .position(|x| x.is_none()) - .unwrap_or(buffer.len()) - }; - (len, Some(len)) - } -} - -impl<T> ExactSizeIterator for TupleBuffer<T> - where T: TupleCollect -{ -} - -/// An iterator that groups the items in tuples of a specific size. -/// -/// See [`.tuples()`](../trait.Itertools.html#method.tuples) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - iter: Fuse<I>, - buf: T::Buffer, -} - -/// Create a new tuples iterator. -pub fn tuples<I, T>(iter: I) -> Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - Tuples { - iter: iter.fuse(), - buf: Default::default(), - } -} - -impl<I, T> Iterator for Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - type Item = T; - - fn next(&mut self) -> Option<T> { - T::collect_from_iter(&mut self.iter, &mut self.buf) - } -} - -impl<I, T> Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - /// Return a buffer with the produced items that was not enough to be grouped in a tuple. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut iter = (0..5).tuples(); - /// assert_eq!(Some((0, 1, 2)), iter.next()); - /// assert_eq!(None, iter.next()); - /// itertools::assert_equal(vec![3, 4], iter.into_buffer()); - /// ``` - pub fn into_buffer(self) -> TupleBuffer<T> { - TupleBuffer::new(self.buf) - } -} - - -/// An iterator over all contiguous windows that produces tuples of a specific size. -/// -/// See [`.tuple_windows()`](../trait.Itertools.html#method.tuple_windows) for more -/// information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct TupleWindows<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - iter: I, - last: Option<T>, -} - -/// Create a new tuple windows iterator. -pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect, - T::Item: Clone -{ - use std::iter::once; - - let mut last = None; - if T::num_items() != 1 { - // put in a duplicate item in front of the tuple; this simplifies - // .next() function. - if let Some(item) = iter.next() { - let iter = once(item.clone()).chain(once(item)).chain(&mut iter); - last = T::collect_from_iter_no_buf(iter); - } - } - - TupleWindows { - last: last, - iter: iter, - } -} - -impl<I, T> Iterator for TupleWindows<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect + Clone, - T::Item: Clone -{ - type Item = T; - - fn next(&mut self) -> Option<T> { - if T::num_items() == 1 { - return T::collect_from_iter_no_buf(&mut self.iter) - } - if let Some(ref mut last) = self.last { - if let Some(new) = self.iter.next() { - last.left_shift_push(new); - return Some(last.clone()); - } - } - None - } -} - -pub trait TupleCollect: Sized { - type Item; - type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>; - - fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self> - where I: IntoIterator<Item = Self::Item>; - - fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self> - where I: IntoIterator<Item = Self::Item>; - - fn num_items() -> usize; - - fn left_shift_push(&mut self, item: Self::Item); -} - -macro_rules! impl_tuple_collect { - () => (); - ($N:expr; $A:ident ; $($X:ident),* ; $($Y:ident),* ; $($Y_rev:ident),*) => ( - impl<$A> TupleCollect for ($($X),*,) { - type Item = $A; - type Buffer = [Option<$A>; $N - 1]; - - #[allow(unused_assignments, unused_mut)] - fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self> - where I: IntoIterator<Item = $A> - { - let mut iter = iter.into_iter(); - $( - let mut $Y = None; - )* - - loop { - $( - $Y = iter.next(); - if $Y.is_none() { - break - } - )* - return Some(($($Y.unwrap()),*,)) - } - - let mut i = 0; - let mut s = buf.as_mut(); - $( - if i < s.len() { - s[i] = $Y; - i += 1; - } - )* - return None; - } - - #[allow(unused_assignments)] - fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self> - where I: IntoIterator<Item = $A> - { - let mut iter = iter.into_iter(); - loop { - $( - let $Y = if let Some($Y) = iter.next() { - $Y - } else { - break; - }; - )* - return Some(($($Y),*,)) - } - - return None; - } - - fn num_items() -> usize { - $N - } - - fn left_shift_push(&mut self, item: $A) { - use std::mem::replace; - - let &mut ($(ref mut $Y),*,) = self; - let tmp = item; - $( - let tmp = replace($Y_rev, tmp); - )* - drop(tmp); - } - } - ) -} - -impl_tuple_collect!(1; A; A; a; a); -impl_tuple_collect!(2; A; A, A; a, b; b, a); -impl_tuple_collect!(3; A; A, A, A; a, b, c; c, b, a); -impl_tuple_collect!(4; A; A, A, A, A; a, b, c, d; d, c, b, a); diff --git a/vendor/itertools-0.7.8/src/unique_impl.rs b/vendor/itertools-0.7.8/src/unique_impl.rs deleted file mode 100644 index d9e7fd3dc8..0000000000 --- a/vendor/itertools-0.7.8/src/unique_impl.rs +++ /dev/null @@ -1,134 +0,0 @@ - -use std::collections::HashMap; -use std::collections::hash_map::{Entry}; -use std::hash::Hash; -use std::fmt; - -/// An iterator adapter to filter out duplicate elements. -/// -/// See [`.unique_by()`](../trait.Itertools.html#method.unique) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct UniqueBy<I: Iterator, V, F> { - iter: I, - // Use a hashmap for the entry API - used: HashMap<V, ()>, - f: F, -} - -impl<I, V, F> fmt::Debug for UniqueBy<I, V, F> - where I: Iterator + fmt::Debug, - V: fmt::Debug + Hash + Eq, -{ - debug_fmt_fields!(UniqueBy, iter, used); -} - -/// Create a new `UniqueBy` iterator. -pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F> - where V: Eq + Hash, - F: FnMut(&I::Item) -> V, - I: Iterator, -{ - UniqueBy { - iter: iter, - used: HashMap::new(), - f: f, - } -} - -// count the number of new unique keys in iterable (`used` is the set already seen) -fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize - where I: IntoIterator<Item=K>, - K: Hash + Eq, -{ - let iter = iterable.into_iter(); - let current_used = used.len(); - used.extend(iter.map(|key| (key, ()))); - used.len() - current_used -} - -impl<I, V, F> Iterator for UniqueBy<I, V, F> - where I: Iterator, - V: Eq + Hash, - F: FnMut(&I::Item) -> V -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - while let Some(v) = self.iter.next() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, hi) = self.iter.size_hint(); - ((low > 0 && self.used.is_empty()) as usize, hi) - } - - fn count(self) -> usize { - let mut key_f = self.f; - count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt))) - } -} - -impl<I> Iterator for Unique<I> - where I: Iterator, - I::Item: Eq + Hash + Clone -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - while let Some(v) = self.iter.iter.next() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { - let elt = entry.key().clone(); - entry.insert(()); - return Some(elt); - } - } - None - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, hi) = self.iter.iter.size_hint(); - ((low > 0 && self.iter.used.is_empty()) as usize, hi) - } - - fn count(self) -> usize { - count_new_keys(self.iter.used, self.iter.iter) - } -} - -/// An iterator adapter to filter out duplicate elements. -/// -/// See [`.unique()`](../trait.Itertools.html#method.unique) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Unique<I: Iterator> { - iter: UniqueBy<I, I::Item, ()>, -} - -impl<I> fmt::Debug for Unique<I> - where I: Iterator + fmt::Debug, - I::Item: Hash + Eq + fmt::Debug, -{ - debug_fmt_fields!(Unique, iter); -} - -pub fn unique<I>(iter: I) -> Unique<I> - where I: Iterator, - I::Item: Eq + Hash, -{ - Unique { - iter: UniqueBy { - iter: iter, - used: HashMap::new(), - f: (), - } - } -} diff --git a/vendor/itertools-0.7.8/src/with_position.rs b/vendor/itertools-0.7.8/src/with_position.rs deleted file mode 100644 index 2a7c2b8ad6..0000000000 --- a/vendor/itertools-0.7.8/src/with_position.rs +++ /dev/null @@ -1,90 +0,0 @@ -use std::iter::{Fuse,Peekable}; - -/// An iterator adaptor that wraps each element in an [`Position`](../enum.Position.html). -/// -/// Iterator element type is `Position<I::Item>`. -/// -/// See [`.with_position()`](../trait.Itertools.html#method.with_position) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct WithPosition<I> - where I: Iterator, -{ - handled_first: bool, - peekable: Peekable<Fuse<I>>, -} - -/// Create a new `WithPosition` iterator. -pub fn with_position<I>(iter: I) -> WithPosition<I> - where I: Iterator, -{ - WithPosition { - handled_first: false, - peekable: iter.fuse().peekable(), - } -} - -/// A value yielded by `WithPosition`. -/// Indicates the position of this element in the iterator results. -/// -/// See [`.with_position()`](trait.Itertools.html#method.with_position) for more information. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Position<T> { - /// This is the first element. - First(T), - /// This is neither the first nor the last element. - Middle(T), - /// This is the last element. - Last(T), - /// This is the only element. - Only(T), -} - -impl<T> Position<T> { - /// Return the inner value. - pub fn into_inner(self) -> T { - match self { - Position::First(x) | - Position::Middle(x) | - Position::Last(x) | - Position::Only(x) => x, - } - } -} - -impl<I: Iterator> Iterator for WithPosition<I> { - type Item = Position<I::Item>; - - fn next(&mut self) -> Option<Self::Item> { - match self.peekable.next() { - Some(item) => { - if !self.handled_first { - // Haven't seen the first item yet, and there is one to give. - self.handled_first = true; - // Peek to see if this is also the last item, - // in which case tag it as `Only`. - match self.peekable.peek() { - Some(_) => Some(Position::First(item)), - None => Some(Position::Only(item)), - } - } else { - // Have seen the first item, and there's something left. - // Peek to see if this is the last item. - match self.peekable.peek() { - Some(_) => Some(Position::Middle(item)), - None => Some(Position::Last(item)), - } - } - } - // Iterator is finished. - None => None, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.peekable.size_hint() - } -} - -impl<I> ExactSizeIterator for WithPosition<I> - where I: ExactSizeIterator, -{ } diff --git a/vendor/itertools-0.7.8/src/zip_eq_impl.rs b/vendor/itertools-0.7.8/src/zip_eq_impl.rs deleted file mode 100644 index 857465da41..0000000000 --- a/vendor/itertools-0.7.8/src/zip_eq_impl.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::size_hint; - -/// An iterator which iterates two other iterators simultaneously -/// -/// See [`.zip_eq()`](../trait.Itertools.html#method.zip_eq) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct ZipEq<I, J> { - a: I, - b: J, -} - -/// Iterate `i` and `j` in lock step. -/// -/// **Panics** if the iterators are not of the same length. -/// -/// `IntoIterator` enabled version of `i.zip_eq(j)`. -/// -/// ``` -/// use itertools::zip_eq; -/// -/// let data = [1, 2, 3, 4, 5]; -/// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) { -/// /* loop body */ -/// } -/// ``` -pub fn zip_eq<I, J>(i: I, j: J) -> ZipEq<I::IntoIter, J::IntoIter> - where I: IntoIterator, - J: IntoIterator -{ - ZipEq { - a: i.into_iter(), - b: j.into_iter(), - } -} - -impl<I, J> Iterator for ZipEq<I, J> - where I: Iterator, - J: Iterator -{ - type Item = (I::Item, J::Item); - - fn next(&mut self) -> Option<Self::Item> { - match (self.a.next(), self.b.next()) { - (None, None) => None, - (Some(a), Some(b)) => Some((a, b)), - (None, Some(_)) | (Some(_), None) => - panic!("itertools: .zip_eq() reached end of one iterator before the other") - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::min(self.a.size_hint(), self.b.size_hint()) - } -} - -impl<I, J> ExactSizeIterator for ZipEq<I, J> - where I: ExactSizeIterator, - J: ExactSizeIterator -{} diff --git a/vendor/itertools-0.7.8/src/zip_longest.rs b/vendor/itertools-0.7.8/src/zip_longest.rs deleted file mode 100644 index 68a381acee..0000000000 --- a/vendor/itertools-0.7.8/src/zip_longest.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::cmp::Ordering::{Equal, Greater, Less}; -use super::size_hint; -use std::iter::Fuse; - -use either_or_both::EitherOrBoth; - -// ZipLongest originally written by SimonSapin, -// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283 - -/// An iterator which iterates two other iterators simultaneously -/// -/// This iterator is *fused*. -/// -/// See [`.zip_longest()`](../trait.Itertools.html#method.zip_longest) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct ZipLongest<T, U> { - a: Fuse<T>, - b: Fuse<U>, -} - -/// Create a new `ZipLongest` iterator. -pub fn zip_longest<T, U>(a: T, b: U) -> ZipLongest<T, U> - where T: Iterator, - U: Iterator -{ - ZipLongest { - a: a.fuse(), - b: b.fuse(), - } -} - -impl<T, U> Iterator for ZipLongest<T, U> - where T: Iterator, - U: Iterator -{ - type Item = EitherOrBoth<T::Item, U::Item>; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - match (self.a.next(), self.b.next()) { - (None, None) => None, - (Some(a), None) => Some(EitherOrBoth::Left(a)), - (None, Some(b)) => Some(EitherOrBoth::Right(b)), - (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::max(self.a.size_hint(), self.b.size_hint()) - } -} - -impl<T, U> DoubleEndedIterator for ZipLongest<T, U> - where T: DoubleEndedIterator + ExactSizeIterator, - U: DoubleEndedIterator + ExactSizeIterator -{ - #[inline] - fn next_back(&mut self) -> Option<Self::Item> { - match self.a.len().cmp(&self.b.len()) { - Equal => match (self.a.next_back(), self.b.next_back()) { - (None, None) => None, - (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), - // These can only happen if .len() is inconsistent with .next_back() - (Some(a), None) => Some(EitherOrBoth::Left(a)), - (None, Some(b)) => Some(EitherOrBoth::Right(b)), - }, - Greater => self.a.next_back().map(EitherOrBoth::Left), - Less => self.b.next_back().map(EitherOrBoth::Right), - } - } -} - -impl<T, U> ExactSizeIterator for ZipLongest<T, U> - where T: ExactSizeIterator, - U: ExactSizeIterator -{} diff --git a/vendor/itertools-0.7.8/src/ziptuple.rs b/vendor/itertools-0.7.8/src/ziptuple.rs deleted file mode 100644 index 2dc3ea5e0b..0000000000 --- a/vendor/itertools-0.7.8/src/ziptuple.rs +++ /dev/null @@ -1,111 +0,0 @@ -use super::size_hint; - -/// See [`multizip`](../fn.multizip.html) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Zip<T> { - t: T, -} - -/// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep. -/// -/// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that -/// implement `IntoIterator`) and yields elements -/// until any of the subiterators yields `None`. -/// -/// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the -/// element types of the subiterator. -/// -/// **Note:** The result of this macro is a value of a named type (`Zip<(I, J, -/// ..)>` of each component iterator `I, J, ...`) if each component iterator is -/// nameable. -/// -/// Prefer [`izip!()`] over `multizip` for the performance benefits of using the -/// standard library `.zip()`. Prefer `multizip` if a nameable type is needed. -/// -/// [`izip!()`]: macro.izip.html -/// -/// ``` -/// use itertools::multizip; -/// -/// // iterate over three sequences side-by-side -/// let mut results = [0, 0, 0, 0]; -/// let inputs = [3, 7, 9, 6]; -/// -/// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) { -/// *r = index * 10 + input; -/// } -/// -/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); -/// ``` -pub fn multizip<T, U>(t: U) -> Zip<T> - where Zip<T>: From<U>, - Zip<T>: Iterator, -{ - Zip::from(t) -} - -macro_rules! impl_zip_iter { - ($($B:ident),*) => ( - #[allow(non_snake_case)] - impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> { - fn from(t: ($($B,)*)) -> Self { - let ($($B,)*) = t; - Zip { t: ($($B.into_iter(),)*) } - } - } - - #[allow(non_snake_case)] - #[allow(unused_assignments)] - impl<$($B),*> Iterator for Zip<($($B,)*)> - where - $( - $B: Iterator, - )* - { - type Item = ($($B::Item,)*); - - fn next(&mut self) -> Option<Self::Item> - { - let ($(ref mut $B,)*) = self.t; - - // NOTE: Just like iter::Zip, we check the iterators - // for None in order. We may finish unevenly (some - // iterators gave n + 1 elements, some only n). - $( - let $B = match $B.next() { - None => return None, - Some(elt) => elt - }; - )* - Some(($($B,)*)) - } - - fn size_hint(&self) -> (usize, Option<usize>) - { - let sh = (::std::usize::MAX, None); - let ($(ref $B,)*) = self.t; - $( - let sh = size_hint::min($B.size_hint(), sh); - )* - sh - } - } - - #[allow(non_snake_case)] - impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where - $( - $B: ExactSizeIterator, - )* - { } - ); -} - -impl_zip_iter!(A); -impl_zip_iter!(A, B); -impl_zip_iter!(A, B, C); -impl_zip_iter!(A, B, C, D); -impl_zip_iter!(A, B, C, D, E); -impl_zip_iter!(A, B, C, D, E, F); -impl_zip_iter!(A, B, C, D, E, F, G); -impl_zip_iter!(A, B, C, D, E, F, G, H); diff --git a/vendor/itertools-0.7.8/tests/merge_join.rs b/vendor/itertools-0.7.8/tests/merge_join.rs deleted file mode 100644 index 41829202b8..0000000000 --- a/vendor/itertools-0.7.8/tests/merge_join.rs +++ /dev/null @@ -1,110 +0,0 @@ -extern crate itertools; - -use itertools::EitherOrBoth; -use itertools::free::merge_join_by; - -#[test] -fn empty() { - let left: Vec<u32> = vec![]; - let right: Vec<u32> = vec![]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn left_only() { - let left: Vec<u32> = vec![1,2,3]; - let right: Vec<u32> = vec![]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Left(2), - EitherOrBoth::Left(3) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn right_only() { - let left: Vec<u32> = vec![]; - let right: Vec<u32> = vec![1,2,3]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Right(1), - EitherOrBoth::Right(2), - EitherOrBoth::Right(3) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn first_left_then_right() { - let left: Vec<u32> = vec![1,2,3]; - let right: Vec<u32> = vec![4,5,6]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Left(2), - EitherOrBoth::Left(3), - EitherOrBoth::Right(4), - EitherOrBoth::Right(5), - EitherOrBoth::Right(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn first_right_then_left() { - let left: Vec<u32> = vec![4,5,6]; - let right: Vec<u32> = vec![1,2,3]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Right(1), - EitherOrBoth::Right(2), - EitherOrBoth::Right(3), - EitherOrBoth::Left(4), - EitherOrBoth::Left(5), - EitherOrBoth::Left(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn interspersed_left_and_right() { - let left: Vec<u32> = vec![1,3,5]; - let right: Vec<u32> = vec![2,4,6]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Right(2), - EitherOrBoth::Left(3), - EitherOrBoth::Right(4), - EitherOrBoth::Left(5), - EitherOrBoth::Right(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn overlapping_left_and_right() { - let left: Vec<u32> = vec![1,3,4,6]; - let right: Vec<u32> = vec![2,3,4,5]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Right(2), - EitherOrBoth::Both(3, 3), - EitherOrBoth::Both(4, 4), - EitherOrBoth::Right(5), - EitherOrBoth::Left(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} diff --git a/vendor/itertools-0.7.8/tests/peeking_take_while.rs b/vendor/itertools-0.7.8/tests/peeking_take_while.rs deleted file mode 100644 index 45c76c2d5c..0000000000 --- a/vendor/itertools-0.7.8/tests/peeking_take_while.rs +++ /dev/null @@ -1,53 +0,0 @@ - -extern crate itertools; - -use itertools::Itertools; -use itertools::{put_back, put_back_n}; - -#[test] -fn peeking_take_while_peekable() { - let mut r = (0..10).peekable(); - r.peeking_take_while(|x| *x <= 3).count(); - assert_eq!(r.next(), Some(4)); -} - -#[test] -fn peeking_take_while_put_back() { - let mut r = put_back(0..10); - r.peeking_take_while(|x| *x <= 3).count(); - assert_eq!(r.next(), Some(4)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} - -#[test] -fn peeking_take_while_put_back_n() { - let mut r = put_back_n(6..10); - for elt in (0..6).rev() { - r.put_back(elt); - } - r.peeking_take_while(|x| *x <= 3).count(); - assert_eq!(r.next(), Some(4)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} - -#[test] -fn peeking_take_while_slice_iter() { - let v = [1, 2, 3, 4, 5, 6]; - let mut r = v.iter(); - r.peeking_take_while(|x| **x <= 3).count(); - assert_eq!(r.next(), Some(&4)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} - -#[test] -fn peeking_take_while_slice_iter_rev() { - let v = [1, 2, 3, 4, 5, 6]; - let mut r = v.iter().rev(); - r.peeking_take_while(|x| **x >= 3).count(); - assert_eq!(r.next(), Some(&2)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} diff --git a/vendor/itertools-0.7.8/tests/quick.rs b/vendor/itertools-0.7.8/tests/quick.rs deleted file mode 100644 index 6859758077..0000000000 --- a/vendor/itertools-0.7.8/tests/quick.rs +++ /dev/null @@ -1,1019 +0,0 @@ -//! The purpose of these tests is to cover corner cases of iterators -//! and adaptors. -//! -//! In particular we test the tedious size_hint and exact size correctness. - -#[macro_use] extern crate itertools; - -extern crate quickcheck; - -use std::default::Default; - -use quickcheck as qc; -use std::ops::Range; -use std::cmp::Ordering; -use itertools::Itertools; -use itertools::{ - multizip, - EitherOrBoth, -}; -use itertools::flatten; -use itertools::free::{ - cloned, - enumerate, - multipeek, - put_back, - put_back_n, - rciter, - zip, - zip_eq, -}; - -use quickcheck::TestResult; - -/// Trait for size hint modifier types -trait HintKind: Copy + Send + qc::Arbitrary { - fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>); -} - -/// Exact size hint variant that leaves hints unchanged -#[derive(Clone, Copy, Debug)] -struct Exact {} - -impl HintKind for Exact { - fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) { - org_hint - } -} - -impl qc::Arbitrary for Exact { - fn arbitrary<G: qc::Gen>(_: &mut G) -> Self { - Exact {} - } -} - -/// Inexact size hint variant to simulate imprecise (but valid) size hints -/// -/// Will always decrease the lower bound and increase the upper bound -/// of the size hint by set amounts. -#[derive(Clone, Copy, Debug)] -struct Inexact { - underestimate: usize, - overestimate: usize, -} - -impl HintKind for Inexact { - fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) { - let (org_lower, org_upper) = org_hint; - (org_lower.saturating_sub(self.underestimate), - org_upper.and_then(move |x| x.checked_add(self.overestimate))) - } -} - -impl qc::Arbitrary for Inexact { - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { - let ue_value = usize::arbitrary(g); - let oe_value = usize::arbitrary(g); - // Compensate for quickcheck using extreme values too rarely - let ue_choices = &[0, ue_value, usize::max_value()]; - let oe_choices = &[0, oe_value, usize::max_value()]; - Inexact { - underestimate: *g.choose(ue_choices).unwrap(), - overestimate: *g.choose(oe_choices).unwrap(), - } - } - - fn shrink(&self) -> Box<Iterator<Item=Self>> { - let underestimate_value = self.underestimate; - let overestimate_value = self.overestimate; - Box::new( - underestimate_value.shrink().flat_map(move |ue_value| - overestimate_value.shrink().map(move |oe_value| - Inexact { - underestimate: ue_value, - overestimate: oe_value, - } - ) - ) - ) - } -} - -/// Our base iterator that we can impl Arbitrary for -/// -/// By default we'll return inexact bounds estimates for size_hint -/// to make tests harder to pass. -/// -/// NOTE: Iter is tricky and is not fused, to help catch bugs. -/// At the end it will return None once, then return Some(0), -/// then return None again. -#[derive(Clone, Debug)] -struct Iter<T, SK: HintKind = Inexact> { - iterator: Range<T>, - // fuse/done flag - fuse_flag: i32, - hint_kind: SK, -} - -impl<T, HK> Iter<T, HK> where HK: HintKind -{ - fn new(it: Range<T>, hint_kind: HK) -> Self { - Iter { - iterator: it, - fuse_flag: 0, - hint_kind: hint_kind - } - } -} - -impl<T, HK> Iterator for Iter<T, HK> - where Range<T>: Iterator, - <Range<T> as Iterator>::Item: Default, - HK: HintKind, -{ - type Item = <Range<T> as Iterator>::Item; - - fn next(&mut self) -> Option<Self::Item> - { - let elt = self.iterator.next(); - if elt.is_none() { - self.fuse_flag += 1; - // check fuse flag - if self.fuse_flag == 2 { - return Some(Default::default()) - } - } - elt - } - - fn size_hint(&self) -> (usize, Option<usize>) - { - let org_hint = self.iterator.size_hint(); - self.hint_kind.loosen_bounds(org_hint) - } -} - -impl<T, HK> DoubleEndedIterator for Iter<T, HK> - where Range<T>: DoubleEndedIterator, - <Range<T> as Iterator>::Item: Default, - HK: HintKind -{ - fn next_back(&mut self) -> Option<Self::Item> { self.iterator.next_back() } -} - -impl<T> ExactSizeIterator for Iter<T, Exact> where Range<T>: ExactSizeIterator, - <Range<T> as Iterator>::Item: Default, -{ } - -impl<T, HK> qc::Arbitrary for Iter<T, HK> - where T: qc::Arbitrary, - HK: HintKind, -{ - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self - { - Iter::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g)) - } - - fn shrink(&self) -> Box<Iterator<Item=Iter<T, HK>>> - { - let r = self.iterator.clone(); - let hint_kind = self.hint_kind; - Box::new( - r.start.shrink().flat_map(move |a| - r.end.shrink().map(move |b| - Iter::new(a.clone()..b, hint_kind) - ) - ) - ) - } -} - -/// A meta-iterator which yields `Iter<i32>`s whose start/endpoints are -/// increased or decreased linearly on each iteration. -#[derive(Clone, Debug)] -struct ShiftRange<HK = Inexact> { - range_start: i32, - range_end: i32, - start_step: i32, - end_step: i32, - iter_count: u32, - hint_kind: HK, -} - -impl<HK> Iterator for ShiftRange<HK> where HK: HintKind { - type Item = Iter<i32, HK>; - - fn next(&mut self) -> Option<Self::Item> { - if self.iter_count == 0 { - return None; - } - - let iter = Iter::new(self.range_start..self.range_end, self.hint_kind); - - self.range_start += self.start_step; - self.range_end += self.end_step; - self.iter_count -= 1; - - Some(iter) - } -} - -impl ExactSizeIterator for ShiftRange<Exact> { } - -impl<HK> qc::Arbitrary for ShiftRange<HK> - where HK: HintKind -{ - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { - const MAX_STARTING_RANGE_DIFF: i32 = 32; - const MAX_STEP_MODULO: i32 = 8; - const MAX_ITER_COUNT: u32 = 3; - - let range_start = qc::Arbitrary::arbitrary(g); - let range_end = range_start + g.gen_range(0, MAX_STARTING_RANGE_DIFF + 1); - let start_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); - let end_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); - let iter_count = g.gen_range(0, MAX_ITER_COUNT + 1); - let hint_kind = qc::Arbitrary::arbitrary(g); - - ShiftRange { - range_start: range_start, - range_end: range_end, - start_step: start_step, - end_step: end_step, - iter_count: iter_count, - hint_kind: hint_kind - } - } -} - -fn correct_size_hint<I: Iterator>(mut it: I) -> bool { - // record size hint at each iteration - let initial_hint = it.size_hint(); - let mut hints = Vec::with_capacity(initial_hint.0 + 1); - hints.push(initial_hint); - while let Some(_) = it.next() { - hints.push(it.size_hint()) - } - - let mut true_count = hints.len(); // start off +1 too much - - // check all the size hints - for &(low, hi) in &hints { - true_count -= 1; - if low > true_count || - (hi.is_some() && hi.unwrap() < true_count) - { - println!("True size: {:?}, size hint: {:?}", true_count, (low, hi)); - //println!("All hints: {:?}", hints); - return false - } - } - true -} - -fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool { - // check every iteration - let (mut low, mut hi) = it.size_hint(); - if Some(low) != hi { return false; } - while let Some(_) = it.next() { - let (xlow, xhi) = it.size_hint(); - if low != xlow + 1 { return false; } - low = xlow; - hi = xhi; - if Some(low) != hi { return false; } - } - let (low, hi) = it.size_hint(); - low == 0 && hi == Some(0) -} - -// Exact size for this case, without ExactSizeIterator -fn exact_size_for_this<I: Iterator>(mut it: I) -> bool { - // check every iteration - let (mut low, mut hi) = it.size_hint(); - if Some(low) != hi { return false; } - while let Some(_) = it.next() { - let (xlow, xhi) = it.size_hint(); - if low != xlow + 1 { return false; } - low = xlow; - hi = xhi; - if Some(low) != hi { return false; } - } - let (low, hi) = it.size_hint(); - low == 0 && hi == Some(0) -} - -/* - * NOTE: Range<i8> is broken! - * (all signed ranges are) -#[quickcheck] -fn size_range_i8(a: Iter<i8>) -> bool { - exact_size(a) -} - -#[quickcheck] -fn size_range_i16(a: Iter<i16>) -> bool { - exact_size(a) -} - -#[quickcheck] -fn size_range_u8(a: Iter<u8>) -> bool { - exact_size(a) -} - */ - -macro_rules! quickcheck { - // accept several property function definitions - // The property functions can use pattern matching and `mut` as usual - // in the function arguments, but the functions can not be generic. - {$($(#$attr:tt)* fn $fn_name:ident($($arg:tt)*) -> $ret:ty { $($code:tt)* })*} => ( - $( - #[test] - $(#$attr)* - fn $fn_name() { - fn prop($($arg)*) -> $ret { - $($code)* - } - ::quickcheck::quickcheck(quickcheck!(@fn prop [] $($arg)*)); - } - )* - ); - // parse argument list (with patterns allowed) into prop as fn(_, _) -> _ - (@fn $f:ident [$($t:tt)*]) => { - $f as fn($($t),*) -> _ - }; - (@fn $f:ident [$($p:tt)*] : $($tail:tt)*) => { - quickcheck!(@fn $f [$($p)* _] $($tail)*) - }; - (@fn $f:ident [$($p:tt)*] $t:tt $($tail:tt)*) => { - quickcheck!(@fn $f [$($p)*] $($tail)*) - }; -} - -quickcheck! { - - fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool { - correct_size_hint(a.cartesian_product(b)) - } - fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool { - correct_size_hint(iproduct!(a, b, c)) - } - - fn correct_cartesian_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>, - take_manual: usize) -> () - { - // test correctness of iproduct through regular iteration (take) - // and through fold. - let ac = a.clone(); - let br = &b.clone(); - let cr = &c.clone(); - let answer: Vec<_> = ac.flat_map(move |ea| br.clone().flat_map(move |eb| cr.clone().map(move |ec| (ea, eb, ec)))).collect(); - let mut product_iter = iproduct!(a, b, c); - let mut actual = Vec::new(); - - actual.extend((&mut product_iter).take(take_manual)); - if actual.len() == take_manual { - product_iter.fold((), |(), elt| actual.push(elt)); - } - assert_eq!(answer, actual); - } - - fn size_multi_product(a: ShiftRange) -> bool { - correct_size_hint(a.multi_cartesian_product()) - } - fn correct_multi_product3(a: ShiftRange, take_manual: usize) -> () { - // Fix no. of iterators at 3 - let a = ShiftRange { iter_count: 3, ..a }; - - // test correctness of MultiProduct through regular iteration (take) - // and through fold. - let mut iters = a.clone(); - let i0 = iters.next().unwrap(); - let i1r = &iters.next().unwrap(); - let i2r = &iters.next().unwrap(); - let answer: Vec<_> = i0.flat_map(move |ei0| i1r.clone().flat_map(move |ei1| i2r.clone().map(move |ei2| vec![ei0, ei1, ei2]))).collect(); - let mut multi_product = a.clone().multi_cartesian_product(); - let mut actual = Vec::new(); - - actual.extend((&mut multi_product).take(take_manual)); - if actual.len() == take_manual { - multi_product.fold((), |(), elt| actual.push(elt)); - } - assert_eq!(answer, actual); - - assert_eq!(answer.into_iter().last(), a.clone().multi_cartesian_product().last()); - } - - fn size_step(a: Iter<i16, Exact>, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let filt = a.clone().dedup(); - correct_size_hint(filt.step(s)) && - exact_size(a.step(s)) - } - fn equal_step(a: Iter<i16>, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let mut i = 0; - itertools::equal(a.clone().step(s), a.filter(|_| { - let keep = i % s == 0; - i += 1; - keep - })) - } - fn equal_step_vec(a: Vec<i16>, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let mut i = 0; - itertools::equal(a.iter().step(s), a.iter().filter(|_| { - let keep = i % s == 0; - i += 1; - keep - })) - } - - fn size_multipeek(a: Iter<u16, Exact>, s: u8) -> bool { - let mut it = multipeek(a); - // peek a few times - for _ in 0..s { - it.peek(); - } - exact_size(it) - } - - fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool { - let mut sa = a.clone(); - let mut sb = b.clone(); - sa.sort(); - sb.sort(); - let mut merged = sa.clone(); - merged.extend(sb.iter().cloned()); - merged.sort(); - itertools::equal(&merged, sa.iter().merge(&sb)) - } - fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool { - correct_size_hint(a.merge(b)) - } - fn size_zip(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool { - let filt = a.clone().dedup(); - correct_size_hint(multizip((filt, b.clone(), c.clone()))) && - exact_size(multizip((a, b, c))) - } - fn size_zip_rc(a: Iter<i16>, b: Iter<i16>) -> bool { - let rc = rciter(a.clone()); - correct_size_hint(multizip((&rc, &rc, b))) - } - - fn size_zip_macro(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool { - let filt = a.clone().dedup(); - correct_size_hint(izip!(filt, b.clone(), c.clone())) && - exact_size(izip!(a, b, c)) - } - fn equal_kmerge(a: Vec<i16>, b: Vec<i16>, c: Vec<i16>) -> bool { - use itertools::free::kmerge; - let mut sa = a.clone(); - let mut sb = b.clone(); - let mut sc = c.clone(); - sa.sort(); - sb.sort(); - sc.sort(); - let mut merged = sa.clone(); - merged.extend(sb.iter().cloned()); - merged.extend(sc.iter().cloned()); - merged.sort(); - itertools::equal(merged.into_iter(), kmerge(vec![sa, sb, sc])) - } - - // Any number of input iterators - fn equal_kmerge_2(mut inputs: Vec<Vec<i16>>) -> bool { - use itertools::free::kmerge; - // sort the inputs - for input in &mut inputs { - input.sort(); - } - let mut merged = inputs.concat(); - merged.sort(); - itertools::equal(merged.into_iter(), kmerge(inputs)) - } - - // Any number of input iterators - fn equal_kmerge_by_ge(mut inputs: Vec<Vec<i16>>) -> bool { - // sort the inputs - for input in &mut inputs { - input.sort(); - input.reverse(); - } - let mut merged = inputs.concat(); - merged.sort(); - merged.reverse(); - itertools::equal(merged.into_iter(), - inputs.into_iter().kmerge_by(|x, y| x >= y)) - } - - // Any number of input iterators - fn equal_kmerge_by_lt(mut inputs: Vec<Vec<i16>>) -> bool { - // sort the inputs - for input in &mut inputs { - input.sort(); - } - let mut merged = inputs.concat(); - merged.sort(); - itertools::equal(merged.into_iter(), - inputs.into_iter().kmerge_by(|x, y| x < y)) - } - - // Any number of input iterators - fn equal_kmerge_by_le(mut inputs: Vec<Vec<i16>>) -> bool { - // sort the inputs - for input in &mut inputs { - input.sort(); - } - let mut merged = inputs.concat(); - merged.sort(); - itertools::equal(merged.into_iter(), - inputs.into_iter().kmerge_by(|x, y| x <= y)) - } - fn size_kmerge(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool { - use itertools::free::kmerge; - correct_size_hint(kmerge(vec![a, b, c])) - } - fn equal_zip_eq(a: Vec<i32>, b: Vec<i32>) -> bool { - let len = std::cmp::min(a.len(), b.len()); - let a = &a[..len]; - let b = &b[..len]; - itertools::equal(zip_eq(a, b), zip(a, b)) - } - fn size_zip_longest(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool { - let filt = a.clone().dedup(); - let filt2 = b.clone().dedup(); - correct_size_hint(filt.zip_longest(b.clone())) && - correct_size_hint(a.clone().zip_longest(filt2)) && - exact_size(a.zip_longest(b)) - } - fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool { - let it = a.clone().zip_longest(b.clone()); - let jt = a.clone().zip_longest(b.clone()); - itertools::equal(a.clone(), - it.filter_map(|elt| match elt { - EitherOrBoth::Both(x, _) => Some(x), - EitherOrBoth::Left(x) => Some(x), - _ => None, - } - )) - && - itertools::equal(b.clone(), - jt.filter_map(|elt| match elt { - EitherOrBoth::Both(_, y) => Some(y), - EitherOrBoth::Right(y) => Some(y), - _ => None, - } - )) - } - fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool { - correct_size_hint(a.interleave(b)) - } - fn exact_interleave(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool { - exact_size_for_this(a.interleave(b)) - } - fn size_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool { - correct_size_hint(a.interleave_shortest(b)) - } - fn exact_interleave_shortest(a: Vec<()>, b: Vec<()>) -> bool { - exact_size_for_this(a.iter().interleave_shortest(&b)) - } - fn size_intersperse(a: Iter<i16>, x: i16) -> bool { - correct_size_hint(a.intersperse(x)) - } - fn equal_intersperse(a: Vec<i32>, x: i32) -> bool { - let mut inter = false; - let mut i = 0; - for elt in a.iter().cloned().intersperse(x) { - if inter { - if elt != x { return false } - } else { - if elt != a[i] { return false } - i += 1; - } - inter = !inter; - } - true - } - - fn equal_flatten(a: Vec<Option<i32>>) -> bool { - itertools::equal(flatten(&a), - a.iter().filter_map(|x| x.as_ref())) - } - - fn equal_flatten_vec(a: Vec<Vec<u8>>) -> bool { - itertools::equal(flatten(&a), - a.iter().flat_map(|x| x)) - } - - fn equal_combinations_2(a: Vec<u8>) -> bool { - let mut v = Vec::new(); - for (i, x) in enumerate(&a) { - for y in &a[i + 1..] { - v.push((x, y)); - } - } - itertools::equal(a.iter().tuple_combinations::<(_, _)>(), v) - } - - fn collect_tuple_matches_size(a: Iter<i16>) -> bool { - let size = a.clone().count(); - a.collect_tuple::<(_, _, _)>().is_some() == (size == 3) - } -} - -quickcheck! { - fn equal_dedup(a: Vec<i32>) -> bool { - let mut b = a.clone(); - b.dedup(); - itertools::equal(&b, a.iter().dedup()) - } -} - -quickcheck! { - fn size_dedup(a: Vec<i32>) -> bool { - correct_size_hint(a.iter().dedup()) - } -} - -quickcheck! { - fn exact_repeatn((n, x): (usize, i32)) -> bool { - let it = itertools::repeat_n(x, n); - exact_size(it) - } -} - -quickcheck! { - fn size_put_back(a: Vec<u8>, x: Option<u8>) -> bool { - let mut it = put_back(a.into_iter()); - match x { - Some(t) => it.put_back(t), - None => {} - } - correct_size_hint(it) - } -} - -quickcheck! { - fn size_put_backn(a: Vec<u8>, b: Vec<u8>) -> bool { - let mut it = put_back_n(a.into_iter()); - for elt in b { - it.put_back(elt) - } - correct_size_hint(it) - } -} - -quickcheck! { - fn size_tee(a: Vec<u8>) -> bool { - let (mut t1, mut t2) = a.iter().tee(); - t1.next(); - t1.next(); - t2.next(); - exact_size(t1) && exact_size(t2) - } -} - -quickcheck! { - fn size_tee_2(a: Vec<u8>) -> bool { - let (mut t1, mut t2) = a.iter().dedup().tee(); - t1.next(); - t1.next(); - t2.next(); - correct_size_hint(t1) && correct_size_hint(t2) - } -} - -quickcheck! { - fn size_take_while_ref(a: Vec<u8>, stop: u8) -> bool { - correct_size_hint(a.iter().take_while_ref(|x| **x != stop)) - } -} - -quickcheck! { - fn equal_partition(a: Vec<i32>) -> bool { - let mut a = a; - let mut ap = a.clone(); - let split_index = itertools::partition(&mut ap, |x| *x >= 0); - let parted = (0..split_index).all(|i| ap[i] >= 0) && - (split_index..a.len()).all(|i| ap[i] < 0); - - a.sort(); - ap.sort(); - parted && (a == ap) - } -} - -quickcheck! { - fn size_combinations(it: Iter<i16>) -> bool { - correct_size_hint(it.tuple_combinations::<(_, _)>()) - } -} - -quickcheck! { - fn equal_combinations(it: Iter<i16>) -> bool { - let values = it.clone().collect_vec(); - let mut cmb = it.tuple_combinations(); - for i in 0..values.len() { - for j in i+1..values.len() { - let pair = (values[i], values[j]); - if pair != cmb.next().unwrap() { - return false; - } - } - } - cmb.next() == None - } -} - -quickcheck! { - fn size_pad_tail(it: Iter<i8>, pad: u8) -> bool { - correct_size_hint(it.clone().pad_using(pad as usize, |_| 0)) && - correct_size_hint(it.dropping(1).rev().pad_using(pad as usize, |_| 0)) - } -} - -quickcheck! { - fn size_pad_tail2(it: Iter<i8, Exact>, pad: u8) -> bool { - exact_size(it.pad_using(pad as usize, |_| 0)) - } -} - -quickcheck! { - fn size_unique(it: Iter<i8>) -> bool { - correct_size_hint(it.unique()) - } - - fn count_unique(it: Vec<i8>, take_first: u8) -> () { - let answer = { - let mut v = it.clone(); - v.sort(); v.dedup(); - v.len() - }; - let mut iter = cloned(&it).unique(); - let first_count = (&mut iter).take(take_first as usize).count(); - let rest_count = iter.count(); - assert_eq!(answer, first_count + rest_count); - } -} - -quickcheck! { - fn fuzz_group_by_lazy_1(it: Iter<u8>) -> bool { - let jt = it.clone(); - let groups = it.group_by(|k| *k); - let res = itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x)); - res - } -} - -quickcheck! { - fn fuzz_group_by_lazy_2(data: Vec<u8>) -> bool { - let groups = data.iter().group_by(|k| *k / 10); - let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); - res - } -} - -quickcheck! { - fn fuzz_group_by_lazy_3(data: Vec<u8>) -> bool { - let grouper = data.iter().group_by(|k| *k / 10); - let groups = grouper.into_iter().collect_vec(); - let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); - res - } -} - -quickcheck! { - fn fuzz_group_by_lazy_duo(data: Vec<u8>, order: Vec<(bool, bool)>) -> bool { - let grouper = data.iter().group_by(|k| *k / 3); - let mut groups1 = grouper.into_iter(); - let mut groups2 = grouper.into_iter(); - let mut elts = Vec::<&u8>::new(); - let mut old_groups = Vec::new(); - - let tup1 = |(_, b)| b; - for &(ord, consume_now) in &order { - let iter = &mut [&mut groups1, &mut groups2][ord as usize]; - match iter.next() { - Some((_, gr)) => if consume_now { - for og in old_groups.drain(..) { - elts.extend(og); - } - elts.extend(gr); - } else { - old_groups.push(gr); - }, - None => break, - } - } - for og in old_groups.drain(..) { - elts.extend(og); - } - for gr in groups1.map(&tup1) { elts.extend(gr); } - for gr in groups2.map(&tup1) { elts.extend(gr); } - itertools::assert_equal(&data, elts); - true - } -} - -quickcheck! { - fn equal_chunks_lazy(a: Vec<u8>, size: u8) -> bool { - let mut size = size; - if size == 0 { - size += 1; - } - let chunks = a.iter().chunks(size as usize); - let it = a.chunks(size as usize); - for (a, b) in chunks.into_iter().zip(it) { - if !itertools::equal(a, b) { - return false; - } - } - true - } -} - -quickcheck! { - fn equal_tuple_windows_1(a: Vec<u8>) -> bool { - let x = a.windows(1).map(|s| (&s[0], )); - let y = a.iter().tuple_windows::<(_,)>(); - itertools::equal(x, y) - } - - fn equal_tuple_windows_2(a: Vec<u8>) -> bool { - let x = a.windows(2).map(|s| (&s[0], &s[1])); - let y = a.iter().tuple_windows::<(_, _)>(); - itertools::equal(x, y) - } - - fn equal_tuple_windows_3(a: Vec<u8>) -> bool { - let x = a.windows(3).map(|s| (&s[0], &s[1], &s[2])); - let y = a.iter().tuple_windows::<(_, _, _)>(); - itertools::equal(x, y) - } - - fn equal_tuple_windows_4(a: Vec<u8>) -> bool { - let x = a.windows(4).map(|s| (&s[0], &s[1], &s[2], &s[3])); - let y = a.iter().tuple_windows::<(_, _, _, _)>(); - itertools::equal(x, y) - } - - fn equal_tuples_1(a: Vec<u8>) -> bool { - let x = a.chunks(1).map(|s| (&s[0], )); - let y = a.iter().tuples::<(_,)>(); - itertools::equal(x, y) - } - - fn equal_tuples_2(a: Vec<u8>) -> bool { - let x = a.chunks(2).filter(|s| s.len() == 2).map(|s| (&s[0], &s[1])); - let y = a.iter().tuples::<(_, _)>(); - itertools::equal(x, y) - } - - fn equal_tuples_3(a: Vec<u8>) -> bool { - let x = a.chunks(3).filter(|s| s.len() == 3).map(|s| (&s[0], &s[1], &s[2])); - let y = a.iter().tuples::<(_, _, _)>(); - itertools::equal(x, y) - } - - fn equal_tuples_4(a: Vec<u8>) -> bool { - let x = a.chunks(4).filter(|s| s.len() == 4).map(|s| (&s[0], &s[1], &s[2], &s[3])); - let y = a.iter().tuples::<(_, _, _, _)>(); - itertools::equal(x, y) - } - - fn exact_tuple_buffer(a: Vec<u8>) -> bool { - let mut iter = a.iter().tuples::<(_, _, _, _)>(); - (&mut iter).last(); - let buffer = iter.into_buffer(); - assert_eq!(buffer.len(), a.len() % 4); - exact_size(buffer) - } -} - -// with_position -quickcheck! { - fn with_position_exact_size_1(a: Vec<u8>) -> bool { - exact_size_for_this(a.iter().with_position()) - } - fn with_position_exact_size_2(a: Iter<u8, Exact>) -> bool { - exact_size_for_this(a.with_position()) - } -} - -quickcheck! { - fn correct_group_map_modulo_key(a: Vec<u8>, modulo: u8) -> () { - let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` - let count = a.len(); - let lookup = a.into_iter().map(|i| (i % modulo, i)).into_group_map(); - - assert_eq!(lookup.values().flat_map(|vals| vals.iter()).count(), count); - - for (&key, vals) in lookup.iter() { - assert!(vals.iter().all(|&val| val % modulo == key)); - } - } -} - -/// A peculiar type: Equality compares both tuple items, but ordering only the -/// first item. This is so we can check the stability property easily. -#[derive(Clone, Debug, PartialEq, Eq)] -struct Val(u32, u32); - -impl PartialOrd<Val> for Val { - fn partial_cmp(&self, other: &Val) -> Option<Ordering> { - self.0.partial_cmp(&other.0) - } -} - -impl Ord for Val { - fn cmp(&self, other: &Val) -> Ordering { - self.0.cmp(&other.0) - } -} - -impl qc::Arbitrary for Val { - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { - let (x, y) = <(u32, u32)>::arbitrary(g); - Val(x, y) - } - fn shrink(&self) -> Box<Iterator<Item = Self>> { - Box::new((self.0, self.1).shrink().map(|(x, y)| Val(x, y))) - } -} - -quickcheck! { - fn minmax(a: Vec<Val>) -> bool { - use itertools::MinMaxResult; - - - let minmax = a.iter().minmax(); - let expected = match a.len() { - 0 => MinMaxResult::NoElements, - 1 => MinMaxResult::OneElement(&a[0]), - _ => MinMaxResult::MinMax(a.iter().min().unwrap(), - a.iter().max().unwrap()), - }; - minmax == expected - } -} - -quickcheck! { - fn minmax_f64(a: Vec<f64>) -> TestResult { - use itertools::MinMaxResult; - - if a.iter().any(|x| x.is_nan()) { - return TestResult::discard(); - } - - let min = cloned(&a).fold1(f64::min); - let max = cloned(&a).fold1(f64::max); - - let minmax = cloned(&a).minmax(); - let expected = match a.len() { - 0 => MinMaxResult::NoElements, - 1 => MinMaxResult::OneElement(min.unwrap()), - _ => MinMaxResult::MinMax(min.unwrap(), max.unwrap()), - }; - TestResult::from_bool(minmax == expected) - } -} - -quickcheck! { - fn tree_fold1_f64(mut a: Vec<f64>) -> TestResult { - fn collapse_adjacent<F>(x: Vec<f64>, mut f: F) -> Vec<f64> - where F: FnMut(f64, f64) -> f64 - { - let mut out = Vec::new(); - for i in (0..x.len()).step(2) { - if i == x.len()-1 { - out.push(x[i]) - } else { - out.push(f(x[i], x[i+1])); - } - } - out - } - - if a.iter().any(|x| x.is_nan()) { - return TestResult::discard(); - } - - let actual = a.iter().cloned().tree_fold1(f64::atan2); - - while a.len() > 1 { - a = collapse_adjacent(a, f64::atan2); - } - let expected = a.pop(); - - TestResult::from_bool(actual == expected) - } -} diff --git a/vendor/itertools-0.7.8/tests/test_core.rs b/vendor/itertools-0.7.8/tests/test_core.rs deleted file mode 100644 index e215255011..0000000000 --- a/vendor/itertools-0.7.8/tests/test_core.rs +++ /dev/null @@ -1,240 +0,0 @@ -//! Licensed under the Apache License, Version 2.0 -//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license -//! http://opensource.org/licenses/MIT, at your -//! option. This file may not be copied, modified, or distributed -//! except according to those terms. -#![no_std] - -#[macro_use] extern crate itertools as it; - -use it::flatten; -use it::Itertools; -use it::interleave; -use it::multizip; -use it::free::put_back; - -#[test] -fn product2() { - let s = "αβ"; - - let mut prod = iproduct!(s.chars(), 0..2); - assert!(prod.next() == Some(('α', 0))); - assert!(prod.next() == Some(('α', 1))); - assert!(prod.next() == Some(('β', 0))); - assert!(prod.next() == Some(('β', 1))); - assert!(prod.next() == None); -} - -#[test] -fn product_temporary() { - for (_x, _y, _z) in iproduct!( - [0, 1, 2].iter().cloned(), - [0, 1, 2].iter().cloned(), - [0, 1, 2].iter().cloned()) - { - // ok - } -} - - -#[test] -fn izip_macro() { - let mut zip = izip!(2..3); - assert!(zip.next() == Some(2)); - assert!(zip.next().is_none()); - - let mut zip = izip!(0..3, 0..2, 0..2i8); - for i in 0..2 { - assert!((i as usize, i, i as i8) == zip.next().unwrap()); - } - assert!(zip.next().is_none()); - - let xs: [isize; 0] = []; - let mut zip = izip!(0..3, 0..2, 0..2i8, &xs); - assert!(zip.next().is_none()); -} - -#[test] -fn izip3() { - let mut zip = multizip((0..3, 0..2, 0..2i8)); - for i in 0..2 { - assert!((i as usize, i, i as i8) == zip.next().unwrap()); - } - assert!(zip.next().is_none()); - - let xs: [isize; 0] = []; - let mut zip = multizip((0..3, 0..2, 0..2i8, xs.iter())); - assert!(zip.next().is_none()); - - for (_, _, _, _, _) in multizip((0..3, 0..2, xs.iter(), &xs, xs.to_vec())) { - /* test compiles */ - } -} - -#[test] -fn write_to() { - let xs = [7, 9, 8]; - let mut ys = [0; 5]; - let cnt = ys.iter_mut().set_from(xs.iter().map(|x| *x)); - assert!(cnt == xs.len()); - assert!(ys == [7, 9, 8, 0, 0]); - - let cnt = ys.iter_mut().set_from(0..10); - assert!(cnt == ys.len()); - assert!(ys == [0, 1, 2, 3, 4]); -} - -#[test] -fn test_interleave() { - let xs: [u8; 0] = []; - let ys = [7u8, 9, 8, 10]; - let zs = [2u8, 77]; - let it = interleave(xs.iter(), ys.iter()); - it::assert_equal(it, ys.iter()); - - let rs = [7u8, 2, 9, 77, 8, 10]; - let it = interleave(ys.iter(), zs.iter()); - it::assert_equal(it, rs.iter()); -} - -#[test] -fn foreach() { - let xs = [1i32, 2, 3]; - let mut sum = 0; - xs.iter().foreach(|elt| sum += *elt); - assert!(sum == 6); -} - -#[test] -fn dropping() { - let xs = [1, 2, 3]; - let mut it = xs.iter().dropping(2); - assert_eq!(it.next(), Some(&3)); - assert!(it.next().is_none()); - let mut it = xs.iter().dropping(5); - assert!(it.next().is_none()); -} - -#[test] -fn batching() { - let xs = [0, 1, 2, 1, 3]; - let ys = [(0, 1), (2, 1)]; - - // An iterator that gathers elements up in pairs - let pit = xs.iter().cloned().batching(|it| { - match it.next() { - None => None, - Some(x) => match it.next() { - None => None, - Some(y) => Some((x, y)), - } - } - }); - it::assert_equal(pit, ys.iter().cloned()); -} - -#[test] -fn test_put_back() { - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let mut pb = put_back(xs.iter().cloned()); - pb.next(); - pb.put_back(1); - pb.put_back(0); - it::assert_equal(pb, xs.iter().cloned()); -} - -#[test] -fn step() { - it::assert_equal((0..10).step(1), 0..10); - it::assert_equal((0..10).step(2), (0..10).filter(|x: &i32| *x % 2 == 0)); - it::assert_equal((0..10).step(10), 0..1); -} - -#[test] -fn merge() { - it::assert_equal((0..10).step(2).merge((1..10).step(2)), 0..10); -} - - -#[test] -fn repeatn() { - let s = "α"; - let mut it = it::repeat_n(s, 3); - assert_eq!(it.len(), 3); - assert_eq!(it.next(), Some(s)); - assert_eq!(it.next(), Some(s)); - assert_eq!(it.next(), Some(s)); - assert_eq!(it.next(), None); - assert_eq!(it.next(), None); -} - -#[test] -fn count_clones() { - // Check that RepeatN only clones N - 1 times. - - use core::cell::Cell; - #[derive(PartialEq, Debug)] - struct Foo { - n: Cell<usize> - } - - impl Clone for Foo - { - fn clone(&self) -> Self - { - let n = self.n.get(); - self.n.set(n + 1); - Foo { n: Cell::new(n + 1) } - } - } - - - for n in 0..10 { - let f = Foo{n: Cell::new(0)}; - let it = it::repeat_n(f, n); - // drain it - let last = it.last(); - if n == 0 { - assert_eq!(last, None); - } else { - assert_eq!(last, Some(Foo{n: Cell::new(n - 1)})); - } - } -} - -#[test] -fn part() { - let mut data = [7, 1, 1, 9, 1, 1, 3]; - let i = it::partition(&mut data, |elt| *elt >= 3); - assert_eq!(i, 3); - assert_eq!(data, [7, 3, 9, 1, 1, 1, 1]); - - let i = it::partition(&mut data, |elt| *elt == 1); - assert_eq!(i, 4); - assert_eq!(data, [1, 1, 1, 1, 9, 3, 7]); - - let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - let i = it::partition(&mut data, |elt| *elt % 3 == 0); - assert_eq!(i, 3); - assert_eq!(data, [9, 6, 3, 4, 5, 2, 7, 8, 1]); -} - -#[test] -fn flatten_clone() { - let data = &[ - &[1,2,3], - &[4,5,6] - ]; - let flattened1 = flatten(data.into_iter().cloned()); - let flattened2 = flattened1.clone(); - - it::assert_equal(flattened1, &[1,2,3,4,5,6]); - it::assert_equal(flattened2, &[1,2,3,4,5,6]); -} - -#[test] -fn tree_fold1() { - for i in 0..100 { - assert_eq!((0..i).tree_fold1(|x, y| x + y), (0..i).fold1(|x, y| x + y)); - } -} diff --git a/vendor/itertools-0.7.8/tests/test_std.rs b/vendor/itertools-0.7.8/tests/test_std.rs deleted file mode 100644 index 35e0529fa8..0000000000 --- a/vendor/itertools-0.7.8/tests/test_std.rs +++ /dev/null @@ -1,749 +0,0 @@ - -#[macro_use] extern crate itertools as it; -extern crate permutohedron; - -use it::flatten; -use it::Itertools; -use it::multizip; -use it::multipeek; -use it::free::rciter; -use it::free::put_back_n; -use it::FoldWhile; -use it::cloned; - -#[test] -fn product3() { - let prod = iproduct!(0..3, 0..2, 0..2); - assert_eq!(prod.size_hint(), (12, Some(12))); - let v = prod.collect_vec(); - for i in 0..3 { - for j in 0..2 { - for k in 0..2 { - assert!((i, j, k) == v[(i * 2 * 2 + j * 2 + k) as usize]); - } - } - } - for (_, _, _, _) in iproduct!(0..3, 0..2, 0..2, 0..3) { - /* test compiles */ - } -} - -#[test] -fn interleave_shortest() { - let v0: Vec<i32> = vec![0, 2, 4]; - let v1: Vec<i32> = vec![1, 3, 5, 7]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5]); - - let v0: Vec<i32> = vec![0, 2, 4, 6, 8]; - let v1: Vec<i32> = vec![1, 3, 5]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5, 6]); - - let i0 = ::std::iter::repeat(0); - let v1: Vec<_> = vec![1, 3, 5]; - let it = i0.interleave_shortest(v1.into_iter()); - assert_eq!(it.size_hint(), (7, Some(7))); - - let v0: Vec<_> = vec![0, 2, 4]; - let i1 = ::std::iter::repeat(1); - let it = v0.into_iter().interleave_shortest(i1); - assert_eq!(it.size_hint(), (6, Some(6))); -} - - -#[test] -fn unique_by() { - let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; - let ys = ["aaa", "bbbbb", "ccc"]; - it::assert_equal(ys.iter(), xs.iter().unique_by(|x| x[..2].to_string())); -} - -#[test] -fn unique() { - let xs = [0, 1, 2, 3, 2, 1, 3]; - let ys = [0, 1, 2, 3]; - it::assert_equal(ys.iter(), xs.iter().unique()); - let xs = [0, 1]; - let ys = [0, 1]; - it::assert_equal(ys.iter(), xs.iter().unique()); -} - -#[test] -fn intersperse() { - let xs = ["a", "", "b", "c"]; - let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect(); - let text: String = v.concat(); - assert_eq!(text, "a, , b, c".to_string()); - - let ys = [0, 1, 2, 3]; - let mut it = ys[..0].iter().map(|x| *x).intersperse(1); - assert!(it.next() == None); -} - -#[test] -fn dedup() { - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let ys = [0, 1, 2, 1, 3]; - it::assert_equal(ys.iter(), xs.iter().dedup()); - let xs = [0, 0, 0, 0, 0]; - let ys = [0]; - it::assert_equal(ys.iter(), xs.iter().dedup()); - - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let ys = [0, 1, 2, 1, 3]; - let mut xs_d = Vec::new(); - xs.iter().dedup().fold((), |(), &elt| xs_d.push(elt)); - assert_eq!(&xs_d, &ys); -} - -#[test] -fn all_equal() { - assert!(!"AABBCCC".chars().all_equal()); - assert!("AAAAAAA".chars().all_equal()); - for (_key, mut sub) in &"AABBCCC".chars().group_by(|&x| x) { - assert!(sub.all_equal()); - } -} - -#[test] -fn test_put_back_n() { - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let mut pb = put_back_n(xs.iter().cloned()); - pb.next(); - pb.next(); - pb.put_back(1); - pb.put_back(0); - it::assert_equal(pb, xs.iter().cloned()); -} - -#[test] -fn tee() { - let xs = [0, 1, 2, 3]; - let (mut t1, mut t2) = xs.iter().cloned().tee(); - assert_eq!(t1.next(), Some(0)); - assert_eq!(t2.next(), Some(0)); - assert_eq!(t1.next(), Some(1)); - assert_eq!(t1.next(), Some(2)); - assert_eq!(t1.next(), Some(3)); - assert_eq!(t1.next(), None); - assert_eq!(t2.next(), Some(1)); - assert_eq!(t2.next(), Some(2)); - assert_eq!(t1.next(), None); - assert_eq!(t2.next(), Some(3)); - assert_eq!(t2.next(), None); - assert_eq!(t1.next(), None); - assert_eq!(t2.next(), None); - - let (t1, t2) = xs.iter().cloned().tee(); - it::assert_equal(t1, xs.iter().cloned()); - it::assert_equal(t2, xs.iter().cloned()); - - let (t1, t2) = xs.iter().cloned().tee(); - it::assert_equal(t1.zip(t2), xs.iter().cloned().zip(xs.iter().cloned())); -} - - -#[test] -fn test_rciter() { - let xs = [0, 1, 1, 1, 2, 1, 3, 5, 6]; - - let mut r1 = rciter(xs.iter().cloned()); - let mut r2 = r1.clone(); - assert_eq!(r1.next(), Some(0)); - assert_eq!(r2.next(), Some(1)); - let mut z = r1.zip(r2); - assert_eq!(z.next(), Some((1, 1))); - assert_eq!(z.next(), Some((2, 1))); - assert_eq!(z.next(), Some((3, 5))); - assert_eq!(z.next(), None); - - // test intoiterator - let r1 = rciter(0..5); - let mut z = izip!(&r1, r1); - assert_eq!(z.next(), Some((0, 1))); -} - -#[test] -fn trait_pointers() { - struct ByRef<'r, I: ?Sized>(&'r mut I) where I: 'r; - - impl<'r, X, I: ?Sized> Iterator for ByRef<'r, I> where - I: 'r + Iterator<Item=X> - { - type Item = X; - fn next(&mut self) -> Option<X> - { - self.0.next() - } - } - - let mut it = Box::new(0..10) as Box<Iterator<Item=i32>>; - assert_eq!(it.next(), Some(0)); - - { - /* make sure foreach works on non-Sized */ - let jt: &mut Iterator<Item = i32> = &mut *it; - assert_eq!(jt.next(), Some(1)); - - { - let mut r = ByRef(jt); - assert_eq!(r.next(), Some(2)); - } - - assert_eq!(jt.find_position(|x| *x == 4), Some((1, 4))); - jt.foreach(|_| ()); - } -} - -#[test] -fn merge_by() { - let odd : Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")]; - let even = vec![(2, "foo"), (4, "bar"), (6, "baz")]; - let expected = vec![(1, "hello"), (2, "foo"), (3, "world"), (4, "bar"), (5, "!"), (6, "baz")]; - let results = odd.iter().merge_by(even.iter(), |a, b| a.0 <= b.0); - it::assert_equal(results, expected.iter()); -} - -#[test] -fn merge_by_btree() { - use std::collections::BTreeMap; - let mut bt1 = BTreeMap::new(); - bt1.insert("hello", 1); - bt1.insert("world", 3); - let mut bt2 = BTreeMap::new(); - bt2.insert("foo", 2); - bt2.insert("bar", 4); - let results = bt1.into_iter().merge_by(bt2.into_iter(), |a, b| a.0 <= b.0 ); - let expected = vec![("bar", 4), ("foo", 2), ("hello", 1), ("world", 3)]; - it::assert_equal(results, expected.into_iter()); -} - -#[test] -fn kmerge() { - let its = (0..4).map(|s| (s..10).step(4)); - - it::assert_equal(its.kmerge(), 0..10); -} - -#[test] -fn kmerge_2() { - let its = vec![3, 2, 1, 0].into_iter().map(|s| (s..10).step(4)); - - it::assert_equal(its.kmerge(), 0..10); -} - -#[test] -fn kmerge_empty() { - let its = (0..4).map(|_| 0..0); - assert_eq!(its.kmerge().next(), None); -} - -#[test] -fn kmerge_size_hint() { - let its = (0..5).map(|_| (0..10)); - assert_eq!(its.kmerge().size_hint(), (50, Some(50))); -} - -#[test] -fn kmerge_empty_size_hint() { - let its = (0..5).map(|_| (0..0)); - assert_eq!(its.kmerge().size_hint(), (0, Some(0))); -} - -#[test] -fn join() { - let many = [1, 2, 3]; - let one = [1]; - let none: Vec<i32> = vec![]; - - assert_eq!(many.iter().join(", "), "1, 2, 3"); - assert_eq!( one.iter().join(", "), "1"); - assert_eq!(none.iter().join(", "), ""); -} - -#[test] -fn sorted_by() { - let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| { - a.cmp(&b) - }); - assert_eq!(sc, vec![1, 2, 3, 4]); - - let v = (0..5).sorted_by(|&a, &b| a.cmp(&b).reverse()); - assert_eq!(v, vec![4, 3, 2, 1, 0]); -} - -#[test] -fn sorted_by_key() { - let sc = [3, 4, 1, 2].iter().cloned().sorted_by_key(|&x| x); - assert_eq!(sc, vec![1, 2, 3, 4]); - - let v = (0..5).sorted_by_key(|&x| -x); - assert_eq!(v, vec![4, 3, 2, 1, 0]); -} - -#[test] -fn test_multipeek() { - let nums = vec![1u8,2,3,4,5]; - - let mp = multipeek(nums.iter().map(|&x| x)); - assert_eq!(nums, mp.collect::<Vec<_>>()); - - let mut mp = multipeek(nums.iter().map(|&x| x)); - assert_eq!(mp.peek(), Some(&1)); - assert_eq!(mp.next(), Some(1)); - assert_eq!(mp.peek(), Some(&2)); - assert_eq!(mp.peek(), Some(&3)); - assert_eq!(mp.next(), Some(2)); - assert_eq!(mp.peek(), Some(&3)); - assert_eq!(mp.peek(), Some(&4)); - assert_eq!(mp.peek(), Some(&5)); - assert_eq!(mp.peek(), None); - assert_eq!(mp.next(), Some(3)); - assert_eq!(mp.next(), Some(4)); - assert_eq!(mp.peek(), Some(&5)); - assert_eq!(mp.peek(), None); - assert_eq!(mp.next(), Some(5)); - assert_eq!(mp.next(), None); - assert_eq!(mp.peek(), None); - -} - -#[test] -fn test_multipeek_reset() { - let data = [1, 2, 3, 4]; - - let mut mp = multipeek(cloned(&data)); - assert_eq!(mp.peek(), Some(&1)); - assert_eq!(mp.next(), Some(1)); - assert_eq!(mp.peek(), Some(&2)); - assert_eq!(mp.peek(), Some(&3)); - mp.reset_peek(); - assert_eq!(mp.peek(), Some(&2)); - assert_eq!(mp.next(), Some(2)); -} - -#[test] -fn test_multipeek_peeking_next() { - use it::PeekingNext; - let nums = vec![1u8,2,3,4,5,6,7]; - - let mut mp = multipeek(nums.iter().map(|&x| x)); - assert_eq!(mp.peeking_next(|&x| x != 0), Some(1)); - assert_eq!(mp.next(), Some(2)); - assert_eq!(mp.peek(), Some(&3)); - assert_eq!(mp.peek(), Some(&4)); - assert_eq!(mp.peeking_next(|&x| x == 3), Some(3)); - assert_eq!(mp.peek(), Some(&4)); - assert_eq!(mp.peeking_next(|&x| x != 4), None); - assert_eq!(mp.peeking_next(|&x| x == 4), Some(4)); - assert_eq!(mp.peek(), Some(&5)); - assert_eq!(mp.peek(), Some(&6)); - assert_eq!(mp.peeking_next(|&x| x != 5), None); - assert_eq!(mp.peek(), Some(&7)); - assert_eq!(mp.peeking_next(|&x| x == 5), Some(5)); - assert_eq!(mp.peeking_next(|&x| x == 6), Some(6)); - assert_eq!(mp.peek(), Some(&7)); - assert_eq!(mp.peek(), None); - assert_eq!(mp.next(), Some(7)); - assert_eq!(mp.peek(), None); -} - -#[test] -fn pad_using() { - it::assert_equal((0..0).pad_using(1, |_| 1), 1..2); - - let v: Vec<usize> = vec![0, 1, 2]; - let r = v.into_iter().pad_using(5, |n| n); - it::assert_equal(r, vec![0, 1, 2, 3, 4]); - - let v: Vec<usize> = vec![0, 1, 2]; - let r = v.into_iter().pad_using(1, |_| panic!()); - it::assert_equal(r, vec![0, 1, 2]); -} - -#[test] -fn group_by() { - for (ch1, sub) in &"AABBCCC".chars().group_by(|&x| x) { - for ch2 in sub { - assert_eq!(ch1, ch2); - } - } - - for (ch1, sub) in &"AAABBBCCCCDDDD".chars().group_by(|&x| x) { - for ch2 in sub { - assert_eq!(ch1, ch2); - if ch1 == 'C' { - break; - } - } - } - - let toupper = |ch: &char| ch.to_uppercase().nth(0).unwrap(); - - // try all possible orderings - for indices in permutohedron::Heap::new(&mut [0, 1, 2, 3]) { - let groups = "AaaBbbccCcDDDD".chars().group_by(&toupper); - let mut subs = groups.into_iter().collect_vec(); - - for &idx in &indices[..] { - let (key, text) = match idx { - 0 => ('A', "Aaa".chars()), - 1 => ('B', "Bbb".chars()), - 2 => ('C', "ccCc".chars()), - 3 => ('D', "DDDD".chars()), - _ => unreachable!(), - }; - assert_eq!(key, subs[idx].0); - it::assert_equal(&mut subs[idx].1, text); - } - } - - let groups = "AAABBBCCCCDDDD".chars().group_by(|&x| x); - let mut subs = groups.into_iter().map(|(_, g)| g).collect_vec(); - - let sd = subs.pop().unwrap(); - let sc = subs.pop().unwrap(); - let sb = subs.pop().unwrap(); - let sa = subs.pop().unwrap(); - for (a, b, c, d) in multizip((sa, sb, sc, sd)) { - assert_eq!(a, 'A'); - assert_eq!(b, 'B'); - assert_eq!(c, 'C'); - assert_eq!(d, 'D'); - } - - // check that the key closure is called exactly n times - { - let mut ntimes = 0; - let text = "AABCCC"; - for (_, sub) in &text.chars().group_by(|&x| { ntimes += 1; x}) { - for _ in sub { - } - } - assert_eq!(ntimes, text.len()); - } - - { - let mut ntimes = 0; - let text = "AABCCC"; - for _ in &text.chars().group_by(|&x| { ntimes += 1; x}) { - } - assert_eq!(ntimes, text.len()); - } - - { - let text = "ABCCCDEEFGHIJJKK"; - let gr = text.chars().group_by(|&x| x); - it::assert_equal(gr.into_iter().flat_map(|(_, sub)| sub), text.chars()); - } -} - -#[test] -fn group_by_lazy_2() { - let data = vec![0, 1]; - let groups = data.iter().group_by(|k| *k); - let gs = groups.into_iter().collect_vec(); - it::assert_equal(data.iter(), gs.into_iter().flat_map(|(_k, g)| g)); - - let data = vec![0, 1, 1, 0, 0]; - let groups = data.iter().group_by(|k| *k); - let mut gs = groups.into_iter().collect_vec(); - gs[1..].reverse(); - it::assert_equal(&[0, 0, 0, 1, 1], gs.into_iter().flat_map(|(_, g)| g)); - - let grouper = data.iter().group_by(|k| *k); - let mut groups = Vec::new(); - for (k, group) in &grouper { - if *k == 1 { - groups.push(group); - } - } - it::assert_equal(&mut groups[0], &[1, 1]); - - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; - let grouper = data.iter().group_by(|k| *k); - let mut groups = Vec::new(); - for (i, (_, group)) in grouper.into_iter().enumerate() { - if i < 2 { - groups.push(group); - } else if i < 4 { - for _ in group { - } - } else { - groups.push(group); - } - } - it::assert_equal(&mut groups[0], &[0, 0, 0]); - it::assert_equal(&mut groups[1], &[1, 1]); - it::assert_equal(&mut groups[2], &[3, 3]); - - // use groups as chunks - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; - let mut i = 0; - let grouper = data.iter().group_by(move |_| { let k = i / 3; i += 1; k }); - for (i, group) in &grouper { - match i { - 0 => it::assert_equal(group, &[0, 0, 0]), - 1 => it::assert_equal(group, &[1, 1, 0]), - 2 => it::assert_equal(group, &[0, 2, 2]), - 3 => it::assert_equal(group, &[3, 3]), - _ => unreachable!(), - } - } -} - -#[test] -fn group_by_lazy_3() { - // test consuming each group on the lap after it was produced - let data = vec![0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; - let grouper = data.iter().group_by(|elt| *elt); - let mut last = None; - for (key, group) in &grouper { - if let Some(gr) = last.take() { - for elt in gr { - assert!(elt != key && i32::abs(elt - key) == 1); - } - } - last = Some(group); - } -} - -#[test] -fn chunks() { - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; - let grouper = data.iter().chunks(3); - for (i, chunk) in grouper.into_iter().enumerate() { - match i { - 0 => it::assert_equal(chunk, &[0, 0, 0]), - 1 => it::assert_equal(chunk, &[1, 1, 0]), - 2 => it::assert_equal(chunk, &[0, 2, 2]), - 3 => it::assert_equal(chunk, &[3, 3]), - _ => unreachable!(), - } - } -} - -#[test] -fn concat_empty() { - let data: Vec<Vec<()>> = Vec::new(); - assert_eq!(data.into_iter().concat(), Vec::new()) -} - -#[test] -fn concat_non_empty() { - let data = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]]; - assert_eq!(data.into_iter().concat(), vec![1,2,3,4,5,6,7,8,9]) -} - -#[test] -fn flatten_iter() { - let data = vec![vec![1,2,3], vec![4,5], vec![], vec![6]]; - it::assert_equal(flatten(data), vec![1,2,3,4,5,6]); -} - -#[test] -fn flatten_fold() { - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let ch = xs.iter().chunks(3); - let mut iter = flatten(&ch); - iter.next(); - let mut xs_d = Vec::new(); - iter.fold((), |(), &elt| xs_d.push(elt)); - assert_eq!(&xs_d[..], &xs[1..]); -} - -#[test] -fn combinations() { - assert!((1..3).combinations(5).next().is_none()); - - let it = (1..3).combinations(2); - it::assert_equal(it, vec![ - vec![1, 2], - ]); - - let it = (1..5).combinations(2); - it::assert_equal(it, vec![ - vec![1, 2], - vec![1, 3], - vec![1, 4], - vec![2, 3], - vec![2, 4], - vec![3, 4], - ]); - - it::assert_equal((0..0).tuple_combinations::<(_, _)>(), <Vec<_>>::new()); - it::assert_equal((0..1).tuple_combinations::<(_, _)>(), <Vec<_>>::new()); - it::assert_equal((0..2).tuple_combinations::<(_, _)>(), vec![(0, 1)]); - - it::assert_equal((0..0).combinations(2), <Vec<Vec<_>>>::new()); - it::assert_equal((0..1).combinations(1), vec![vec![0]]); - it::assert_equal((0..2).combinations(1), vec![vec![0], vec![1]]); - it::assert_equal((0..2).combinations(2), vec![vec![0, 1]]); -} - -#[test] -fn combinations_of_too_short() { - for i in 1..10 { - assert!((0..0).combinations(i).next().is_none()); - assert!((0..i - 1).combinations(i).next().is_none()); - } -} - - -#[test] -fn combinations_zero() { - it::assert_equal((1..3).combinations(0), vec![vec![]]); -} - -#[test] -fn diff_mismatch() { - let a = vec![1, 2, 3, 4]; - let b = vec![1.0, 5.0, 3.0, 4.0]; - let b_map = b.into_iter().map(|f| f as i32); - let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); - - assert!(match diff { - Some(it::Diff::FirstMismatch(1, _, from_diff)) => - from_diff.collect::<Vec<_>>() == vec![5, 3, 4], - _ => false, - }); -} - -#[test] -fn diff_longer() { - let a = vec![1, 2, 3, 4]; - let b = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; - let b_map = b.into_iter().map(|f| f as i32); - let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); - - assert!(match diff { - Some(it::Diff::Longer(_, remaining)) => - remaining.collect::<Vec<_>>() == vec![5, 6], - _ => false, - }); -} - -#[test] -fn diff_shorter() { - let a = vec![1, 2, 3, 4]; - let b = vec![1.0, 2.0]; - let b_map = b.into_iter().map(|f| f as i32); - let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); - - assert!(match diff { - Some(it::Diff::Shorter(len, _)) => len == 2, - _ => false, - }); -} - -#[test] -fn minmax() { - use std::cmp::Ordering; - use it::MinMaxResult; - - // A peculiar type: Equality compares both tuple items, but ordering only the - // first item. This is so we can check the stability property easily. - #[derive(Clone, Debug, PartialEq, Eq)] - struct Val(u32, u32); - - impl PartialOrd<Val> for Val { - fn partial_cmp(&self, other: &Val) -> Option<Ordering> { - self.0.partial_cmp(&other.0) - } - } - - impl Ord for Val { - fn cmp(&self, other: &Val) -> Ordering { - self.0.cmp(&other.0) - } - } - - assert_eq!(None::<Option<u32>>.iter().minmax(), MinMaxResult::NoElements); - - assert_eq!(Some(1u32).iter().minmax(), MinMaxResult::OneElement(&1)); - - let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; - - let minmax = data.iter().minmax(); - assert_eq!(minmax, MinMaxResult::MinMax(&Val(0, 1), &Val(2, 1))); - - let (min, max) = data.iter().minmax_by_key(|v| v.1).into_option().unwrap(); - assert_eq!(min, &Val(2, 0)); - assert_eq!(max, &Val(0, 2)); - - let (min, max) = data.iter().minmax_by(|x, y| x.1.cmp(&y.1)).into_option().unwrap(); - assert_eq!(min, &Val(2, 0)); - assert_eq!(max, &Val(0, 2)); -} - -#[test] -fn format() { - let data = [0, 1, 2, 3]; - let ans1 = "0, 1, 2, 3"; - let ans2 = "0--1--2--3"; - - let t1 = format!("{}", data.iter().format(", ")); - assert_eq!(t1, ans1); - let t2 = format!("{:?}", data.iter().format("--")); - assert_eq!(t2, ans2); - - let dataf = [1.1, 2.71828, -22.]; - let t3 = format!("{:.2e}", dataf.iter().format(", ")); - assert_eq!(t3, "1.10e0, 2.72e0, -2.20e1"); -} - -#[test] -fn while_some() { - let ns = (1..10).map(|x| if x % 5 != 0 { Some(x) } else { None }) - .while_some(); - it::assert_equal(ns, vec![1, 2, 3, 4]); -} - -#[test] -fn fold_while() { - let mut iterations = 0; - let vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let sum = vec.into_iter().fold_while(0, |acc, item| { - iterations += 1; - let new_sum = acc.clone() + item; - if new_sum <= 20 { - FoldWhile::Continue(new_sum) - } else { - FoldWhile::Done(acc) - } - }).into_inner(); - assert_eq!(iterations, 6); - assert_eq!(sum, 15); -} - -#[test] -fn tree_fold1() { - let x = [ - "", - "0", - "0 1 x", - "0 1 x 2 x", - "0 1 x 2 3 x x", - "0 1 x 2 3 x x 4 x", - "0 1 x 2 3 x x 4 5 x x", - "0 1 x 2 3 x x 4 5 x 6 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 15 x x x x", - ]; - for (i, &s) in x.iter().enumerate() { - let expected = if s == "" { None } else { Some(s.to_string()) }; - let num_strings = (0..i).map(|x| x.to_string()); - let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b)); - assert_eq!(actual, expected); - } -} diff --git a/vendor/itertools-0.7.8/tests/tuples.rs b/vendor/itertools-0.7.8/tests/tuples.rs deleted file mode 100644 index 07dba57fe6..0000000000 --- a/vendor/itertools-0.7.8/tests/tuples.rs +++ /dev/null @@ -1,88 +0,0 @@ -extern crate itertools; - -use itertools::Itertools; - -#[test] -fn tuples() { - let v = [1, 2, 3, 4, 5]; - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1,)), iter.next()); - assert_eq!(Some((2,)), iter.next()); - assert_eq!(Some((3,)), iter.next()); - assert_eq!(Some((4,)), iter.next()); - assert_eq!(Some((5,)), iter.next()); - assert_eq!(None, iter.next()); - assert_eq!(None, iter.into_buffer().next()); - - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1, 2)), iter.next()); - assert_eq!(Some((3, 4)), iter.next()); - assert_eq!(None, iter.next()); - itertools::assert_equal(vec![5], iter.into_buffer()); - - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1, 2, 3)), iter.next()); - assert_eq!(None, iter.next()); - itertools::assert_equal(vec![4, 5], iter.into_buffer()); - - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1, 2, 3, 4)), iter.next()); - assert_eq!(None, iter.next()); - itertools::assert_equal(vec![5], iter.into_buffer()); -} - -#[test] -fn tuple_windows() { - let v = [1, 2, 3, 4, 5]; - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1,)), iter.next()); - assert_eq!(Some((2,)), iter.next()); - assert_eq!(Some((3,)), iter.next()); - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1, 2)), iter.next()); - assert_eq!(Some((2, 3)), iter.next()); - assert_eq!(Some((3, 4)), iter.next()); - assert_eq!(Some((4, 5)), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1, 2, 3)), iter.next()); - assert_eq!(Some((2, 3, 4)), iter.next()); - assert_eq!(Some((3, 4, 5)), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1, 2, 3, 4)), iter.next()); - assert_eq!(Some((2, 3, 4, 5)), iter.next()); - assert_eq!(None, iter.next()); - - let v = [1, 2, 3]; - let mut iter = v.iter().cloned().tuple_windows::<(_, _, _, _)>(); - assert_eq!(None, iter.next()); -} - -#[test] -fn next_tuple() { - let v = [1, 2, 3, 4, 5]; - let mut iter = v.iter(); - assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((1, 2))); - assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((3, 4))); - assert_eq!(iter.next_tuple::<(_, _)>(), None); -} - -#[test] -fn collect_tuple() { - let v = [1, 2]; - let iter = v.iter().cloned(); - assert_eq!(iter.collect_tuple(), Some((1, 2))); - - let v = [1]; - let iter = v.iter().cloned(); - assert_eq!(iter.collect_tuple::<(_, _)>(), None); - - let v = [1, 2, 3]; - let iter = v.iter().cloned(); - assert_eq!(iter.collect_tuple::<(_, _)>(), None); -} diff --git a/vendor/itertools-0.7.8/tests/zip.rs b/vendor/itertools-0.7.8/tests/zip.rs deleted file mode 100644 index c5c51899b8..0000000000 --- a/vendor/itertools-0.7.8/tests/zip.rs +++ /dev/null @@ -1,65 +0,0 @@ -extern crate itertools; - -use itertools::Itertools; -use itertools::EitherOrBoth::{Both, Left, Right}; -use itertools::free::zip_eq; - -#[test] -fn zip_longest_fused() { - let a = [Some(1), None, Some(3), Some(4)]; - let b = [1, 2, 3]; - - let unfused = a.iter().batching(|it| *it.next().unwrap()) - .zip_longest(b.iter().cloned()); - itertools::assert_equal(unfused, - vec![Both(1, 1), Right(2), Right(3)]); -} - -#[test] -fn test_zip_longest_size_hint() { - let c = (1..10).cycle(); - let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let v2 = &[10, 11, 12]; - - assert_eq!(c.zip_longest(v.iter()).size_hint(), (std::usize::MAX, None)); - - assert_eq!(v.iter().zip_longest(v2.iter()).size_hint(), (10, Some(10))); -} - -#[test] -fn test_double_ended_zip_longest() { - let xs = [1, 2, 3, 4, 5, 6]; - let ys = [1, 2, 3, 7]; - let a = xs.iter().map(|&x| x); - let b = ys.iter().map(|&x| x); - let mut it = a.zip_longest(b); - assert_eq!(it.next(), Some(Both(1, 1))); - assert_eq!(it.next(), Some(Both(2, 2))); - assert_eq!(it.next_back(), Some(Left(6))); - assert_eq!(it.next_back(), Some(Left(5))); - assert_eq!(it.next_back(), Some(Both(4, 7))); - assert_eq!(it.next(), Some(Both(3, 3))); - assert_eq!(it.next(), None); -} - - -#[should_panic] -#[test] -fn zip_eq_panic1() -{ - let a = [1, 2]; - let b = [1, 2, 3]; - - zip_eq(&a, &b).count(); -} - -#[should_panic] -#[test] -fn zip_eq_panic2() -{ - let a: [i32; 0] = []; - let b = [1, 2, 3]; - - zip_eq(&a, &b).count(); -} - diff --git a/vendor/itoa/.cargo-checksum.json b/vendor/itoa/.cargo-checksum.json index 4ce9cb0a67..0c5f193e42 100644 --- a/vendor/itoa/.cargo-checksum.json +++ b/vendor/itoa/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"756bd6e9dbd336547e8e982770c4dc36f67cd0b5d90656033f86cf450879674a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"57b4b49c5ceea9cf94e3856537c01cc1a7e3d071b04d5f5d45155259bfcb83b3","benches/bench.rs":"c4225d539bbc4cee704dcfe59222879b4084bf67d74e0fa973faa69e238c1ff3","src/lib.rs":"21e1c5aa3592989b2a9420303f2fc509b3e55ec7f0ceb2ea01f7fd89758c2cdf","src/udiv128.rs":"efafb66d62b8229478a448ffb3e11a8ad57f5b336aadd59d5b3bf945cfffba96","tests/test.rs":"bca26710b88200a92b0272da6a396a95919a3294a82f928f699b03bd84a838e3"},"package":"1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"} \ No newline at end of file +{"files":{"Cargo.toml":"f744809613f4bebac2bce3256ffde0044d9f0cda6adcb2fd0cc462d2afb8ad98","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"398a1f9022fdf54c13326688a2ba060dfb4b247b45cfc731aad00eba39442f2d","benches/bench.rs":"65020d3ef575c4f9aa9f09ab28dc4164d98207515301d7d16b57c3e48d84049d","src/lib.rs":"c818bec8a1e3522f2b34dd7f8c8f36ca26a368e028c96e3c5771cf57a18158fc","src/udiv128.rs":"16c27cc61f69ca79eca3ac624d6baceaccdbf27cfa43c85c7e065c1ff1481748","tests/test.rs":"428d30ab57b412211a6a0faa7ac36b359e37572b259cd05ac56f4dff6078e896"},"package":"501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"} \ No newline at end of file diff --git a/vendor/itoa/Cargo.toml b/vendor/itoa/Cargo.toml index dd56fee2c6..0563bc1af4 100644 --- a/vendor/itoa/Cargo.toml +++ b/vendor/itoa/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "itoa" -version = "0.4.3" +version = "0.4.4" authors = ["David Tolnay <dtolnay@gmail.com>"] exclude = ["performance.png"] description = "Fast functions for printing integer primitives to an io::Write" diff --git a/vendor/itoa/README.md b/vendor/itoa/README.md index 759be9d204..d36f4fd51c 100644 --- a/vendor/itoa/README.md +++ b/vendor/itoa/README.md @@ -3,41 +3,63 @@ itoa [![Build Status](https://api.travis-ci.org/dtolnay/itoa.svg?branch=master)](https://travis-ci.org/dtolnay/itoa) [![Latest Version](https://img.shields.io/crates/v/itoa.svg)](https://crates.io/crates/itoa) +[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/itoa) This crate provides fast functions for printing integer primitives to an -[`io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) or a -[`fmt::Write`](https://doc.rust-lang.org/core/fmt/trait.Write.html). The -implementation comes straight from -[libcore](https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254) -but avoids the performance penalty of going through -[`fmt::Formatter`](https://doc.rust-lang.org/std/fmt/struct.Formatter.html). +[`io::Write`] or a [`fmt::Write`]. The implementation comes straight from +[libcore] but avoids the performance penalty of going through +[`fmt::Formatter`]. -See also [`dtoa`](https://github.com/dtolnay/dtoa) for printing floating point -primitives. +See also [`dtoa`] for printing floating point primitives. + +*Version requirement: rustc 1.0+* + +[`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +[`fmt::Write`]: https://doc.rust-lang.org/core/fmt/trait.Write.html +[libcore]: https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254 +[`fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html +[`dtoa`]: https://github.com/dtolnay/dtoa + +```toml +[dependencies] +itoa = "0.4" +``` + +<br> ## Performance (lower is better) ![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png) -## Functions +<br> + +## Examples ```rust -extern crate itoa; - -// write to a vector or other io::Write -let mut buf = Vec::new(); -itoa::write(&mut buf, 128u64)?; -println!("{:?}", buf); - -// write to a stack buffer -let mut bytes = [b'\0'; 20]; -let n = itoa::write(&mut bytes[..], 128u64)?; -println!("{:?}", &bytes[..n]); - -// write to a String -let mut s = String::new(); -itoa::fmt(&mut s, 128u64)?; -println!("{}", s); +use std::{fmt, io}; + +fn demo_itoa_write() -> io::Result<()> { + // Write to a vector or other io::Write. + let mut buf = Vec::new(); + itoa::write(&mut buf, 128u64)?; + println!("{:?}", buf); + + // Write to a stack buffer. + let mut bytes = [0u8; 20]; + let n = itoa::write(&mut bytes[..], 128u64)?; + println!("{:?}", &bytes[..n]); + + Ok(()) +} + +fn demo_itoa_fmt() -> fmt::Result { + // Write to a string. + let mut s = String::new(); + itoa::fmt(&mut s, 128u64)?; + println!("{}", s); + + Ok(()) +} ``` The function signatures are: @@ -48,35 +70,26 @@ fn write<W: io::Write, V: itoa::Integer>(writer: W, value: V) -> io::Result<usiz fn fmt<W: fmt::Write, V: itoa::Integer>(writer: W, value: V) -> fmt::Result; ``` -where `itoa::Integer` is implemented for `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, -`i64`, `u64`, `i128`, `u128`, `isize` and `usize`. 128-bit integer support is -only available with the nightly compiler when the `i128` feature is enabled for -this crate. The return value gives the number of bytes written. +where `itoa::Integer` is implemented for i8, u8, i16, u16, i32, u32, i64, u64, +i128, u128, isize and usize. 128-bit integer support requires rustc 1.26+ and +the `i128` feature of this crate enabled. The `write` function is only available when the `std` feature is enabled -(default is enabled). - -## Dependency - -Itoa is available on [crates.io](https://crates.io/crates/itoa). Use the -following in `Cargo.toml`: - -```toml -[dependencies] -itoa = "0.4" -``` - -## License +(default is enabled). The return value gives the number of bytes written. -Licensed under either of +<br> - * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +#### License -at your option. +<sup> +Licensed under either of <a href="LICENSE-APACHE">Apache License, Version +2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. +</sup> -### Contribution +<br> +<sub> Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in itoa by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. +</sub> diff --git a/vendor/itoa/benches/bench.rs b/vendor/itoa/benches/bench.rs index 8f5f25d637..c3b55000b9 100644 --- a/vendor/itoa/benches/bench.rs +++ b/vendor/itoa/benches/bench.rs @@ -1,4 +1,3 @@ -#![cfg_attr(feature = "i128", feature(i128_type, i128))] #![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] #![feature(test)] #![allow(non_snake_case)] diff --git a/vendor/itoa/src/lib.rs b/vendor/itoa/src/lib.rs index 3122f7c5a0..323bb6e2fe 100644 --- a/vendor/itoa/src/lib.rs +++ b/vendor/itoa/src/lib.rs @@ -1,16 +1,59 @@ -// Copyright 2016 Itoa Developers -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![doc(html_root_url = "https://docs.rs/itoa/0.4.3")] +//! This crate provides fast functions for printing integer primitives to an +//! [`io::Write`] or a [`fmt::Write`]. The implementation comes straight from +//! [libcore] but avoids the performance penalty of going through +//! [`fmt::Formatter`]. +//! +//! See also [`dtoa`] for printing floating point primitives. +//! +//! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +//! [`fmt::Write`]: https://doc.rust-lang.org/core/fmt/trait.Write.html +//! [libcore]: https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254 +//! [`fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html +//! [`dtoa`]: https://github.com/dtolnay/dtoa +//! +//! <br> +//! +//! # Performance (lower is better) +//! +//! ![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png) +//! +//! <br> +//! +//! # Examples +//! +//! ```edition2018 +//! use std::{fmt, io}; +//! +//! fn demo_itoa_write() -> io::Result<()> { +//! // Write to a vector or other io::Write. +//! let mut buf = Vec::new(); +//! itoa::write(&mut buf, 128u64)?; +//! println!("{:?}", buf); +//! +//! // Write to a stack buffer. +//! let mut bytes = [0u8; 20]; +//! let n = itoa::write(&mut bytes[..], 128u64)?; +//! println!("{:?}", &bytes[..n]); +//! +//! Ok(()) +//! } +//! +//! fn demo_itoa_fmt() -> fmt::Result { +//! // Write to a string. +//! let mut s = String::new(); +//! itoa::fmt(&mut s, 128u64)?; +//! println!("{}", s); +//! +//! Ok(()) +//! } +//! ``` + +#![doc(html_root_url = "https://docs.rs/itoa/0.4.4")] #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr( feature = "cargo-clippy", - allow(cast_lossless, unreadable_literal) + allow(const_static_lifetime, transmute_ptr_to_ptr), )] #[cfg(feature = "i128")] @@ -43,7 +86,7 @@ pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result { /// /// # Example /// -/// ```rust +/// ``` /// let mut buffer = itoa::Buffer::new(); /// let printed = buffer.format(1234); /// assert_eq!(printed, "1234"); @@ -95,7 +138,7 @@ mod private { pub trait Integer: private::Sealed { // Not public API. #[doc(hidden)] - fn write<'a>(self, buf: &'a mut Buffer) -> &'a str; + fn write(self, buf: &mut Buffer) -> &str; } trait IntegerPrivate<B> { @@ -115,7 +158,7 @@ macro_rules! impl_IntegerCommon { ($max_len:expr, $t:ident) => { impl Integer for $t { #[inline] - fn write<'a>(self, buf: &'a mut Buffer) -> &'a str { + fn write(self, buf: &mut Buffer) -> &str { unsafe { debug_assert!($max_len <= I128_MAX_LEN); let buf = mem::transmute::<&mut [u8; I128_MAX_LEN], &mut [u8; $max_len]>( diff --git a/vendor/itoa/src/udiv128.rs b/vendor/itoa/src/udiv128.rs index 70fffc6baf..adbdce2272 100644 --- a/vendor/itoa/src/udiv128.rs +++ b/vendor/itoa/src/udiv128.rs @@ -1,25 +1,23 @@ -// Copyright 2009-2016 compiler-builtins Developers -// -// The compiler-builtins crate is dual licensed under both the University of -// Illinois "BSD-Like" license and the MIT license. As a user of this code you may -// choose to use it under either license. As a contributor, you agree to allow -// your code to be used under both. +// The code in this file is based on Rust's compiler-builtins crate. The Rust +// compiler automatically links programs against this crate for target-specific +// runtime support. We have copied the implementation of `__udivmodti4()` which +// is an intrinsic implementing division with remainder for architectures +// without 128-bit integers. This implementation works around some poor codegen +// by LLVM (https://github.com/rust-lang/rust/issues/44545) and allows for +// inlining which does not happen with the intrinsic. // -// Full text of the relevant licenses is found here: +// The compiler-builtins crate carries the following license, which is available +// in full at: // https://github.com/rust-lang-nursery/compiler-builtins/blob/master/LICENSE.TXT // +// --- // +// Copyright 2009-2016 compiler-builtins Developers // -// The following code is based on Rust’s [compiler-builtins crate] -// (https://github.com/rust-lang-nursery/compiler-builtins) which -// provides runtime functions for the Rust programs. The Rust -// compiler will automatically link your programs against this crate. -// -// We copied the implementation of '__udivmodti4()' which is an intrinsic -// implementing division with remainder for architectures without 128-bit integer support. -// We have done this two reasons, to work around [bad optimization by LLVM] -// (https://github.com/rust-lang/rust/issues/44545) and to allow function -// inlining which doesn’t happen with the intrinsic. +// The compiler-builtins crate is dual licensed under both the University of +// Illinois "BSD-Like" license and the MIT license. As a user of this code you +// may choose to use it under either license. As a contributor, you agree to +// allow your code to be used under both. #[inline] pub fn udivmod_1e19(n: u128) -> (u128, u64) { diff --git a/vendor/itoa/tests/test.rs b/vendor/itoa/tests/test.rs index 8047f3312b..dd8d4948a4 100644 --- a/vendor/itoa/tests/test.rs +++ b/vendor/itoa/tests/test.rs @@ -1,4 +1,3 @@ -#![cfg_attr(feature = "i128", feature(i128_type, i128))] #![cfg_attr( feature = "cargo-clippy", allow(cast_lossless, string_lit_as_bytes) diff --git a/vendor/markup5ever/.cargo-checksum.json b/vendor/markup5ever/.cargo-checksum.json index 03d41d36fa..e17a4b2502 100644 --- a/vendor/markup5ever/.cargo-checksum.json +++ b/vendor/markup5ever/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"2e6b5ea98ee84a83f5e00c2453b6f7f370728ad7576b2243dcc2679a65a5fe62","build.rs":"3afd9978e7998023385cde7bd3ff155184cae250b25837abb11c1e76e86f7739","data/entities.json":"3d029331b82668ac319bc81802de45b24396df76816d9ba6cf8807c0a1e59a29","data/mod.rs":"4d032db44f246dabeb2e0aadc649ee4bd9409830bbfd008ee95aadb506599049","interface/mod.rs":"3595c0259cd1dd10abbe5a91a44272b3bbbc507cf9ce22f74cf68aef0618b41a","interface/tree_builder.rs":"af9a7394a5c9b904dc8cafc7b4ef0d53e70334a2a8364c9bf2a98eebe79a05e8","lib.rs":"4d0da3b11cb5790f68f2e0f8ad8bff935fe336a7b9631eb462d3680d6f52d813","local_names.txt":"a525722056ada46c5146264d0828df203cf975166c649ba31b3584221e116568","rcdom.rs":"8487f629fe0fb4f12a77c174d3f4511d57b9732fb561f7fe3178acdee1474b30","serialize.rs":"2f42e2a5a08e712ad2fb8a7072ec3e981a6df8c094d16a76e83fc6db47a53c2b","util/buffer_queue.rs":"c88ab5cf5614b2b8e0c53e1212093c80f6b172104a434450137a3b70f9c8df01","util/smallcharset.rs":"305c2d9ec7e8d23170181f994865358aabd1c75d7bdaaba0328e75807635f8d6"},"package":"bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"} \ No newline at end of file +{"files":{"Cargo.toml":"a1250011e9ffa0cd4a23d092fc128867a8043effeb680a00005f4f0c3bed0532","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"86dd7f026f916daf7511e39951ad8ea8cf55a8db67ae64060dacf829761c18f3","build.rs":"45b2179870787e6d423a3ac2cc34323bc09a9e852e1238e251b637c0e9aa2134","data/entities.json":"3d029331b82668ac319bc81802de45b24396df76816d9ba6cf8807c0a1e59a29","data/mod.rs":"0fa4ca8cf1f10b0fb0a56277d688f124355ceeb184986b260f6e2e034967c6b7","interface/mod.rs":"a342fd7d82c42c9f55f5657a10457c0929a236b47ed2eb11648e86c1306e05dd","interface/tree_builder.rs":"4184585a2eefd5838de2bf77daeb77ab7500814cec55761646c69be8080d49ba","lib.rs":"c55ce224048c38db62d9cbe1703faa71954bd941119a51d536edfaaddbc29be8","local_names.txt":"aa721a5481bb64d9697950d60e1c2c09c55cfe032d69aa356808ed2e33e76343","rcdom.rs":"25aaf43ecebaad1903a0f9b2962f3171df878c22f8f4a3e661ff6bd5818fa831","serialize.rs":"68c23f28ca5ba75018724bda29564da8b955be0e6184e2bfd62197e2b38140fa","util/buffer_queue.rs":"0fee064cfba6c92e84b361a3bd49222ecc1639a2a1192b6e523349968d4e6916","util/smallcharset.rs":"13a91adc6a1ce35172577c7a87d8b3005edc5621cbcbd6f1d6c7c123c396d6ba"},"package":"f1af46a727284117e09780d05038b1ce6fc9c76cc6df183c3dae5a8955a25e21"} \ No newline at end of file diff --git a/vendor/markup5ever/Cargo.toml b/vendor/markup5ever/Cargo.toml index f8b5155471..59320cf267 100644 --- a/vendor/markup5ever/Cargo.toml +++ b/vendor/markup5ever/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "markup5ever" -version = "0.7.2" +version = "0.8.1" authors = ["The html5ever Project Developers"] build = "build.rs" description = "Common code for xml5ever and html5ever" @@ -23,6 +23,9 @@ repository = "https://github.com/servo/html5ever" [lib] path = "lib.rs" +[dependencies.log] +version = "0.4" + [dependencies.phf] version = "0.7" diff --git a/vendor/markup5ever/LICENSE-APACHE b/vendor/markup5ever/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/vendor/markup5ever/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/markup5ever/LICENSE-MIT b/vendor/markup5ever/LICENSE-MIT new file mode 100644 index 0000000000..6e4510217d --- /dev/null +++ b/vendor/markup5ever/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 The html5ever Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/markup5ever/build.rs b/vendor/markup5ever/build.rs index b4751d6c40..427e236ad3 100644 --- a/vendor/markup5ever/build.rs +++ b/vendor/markup5ever/build.rs @@ -7,17 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate string_cache_codegen; extern crate phf_codegen; +extern crate string_cache_codegen; #[macro_use] extern crate serde_derive; extern crate serde_json; use std::collections::HashMap; -#[allow(unused_imports)] use std::ascii::AsciiExt; use std::env; use std::fs::File; -use std::io::{Write, BufWriter, BufReader, BufRead}; +use std::io::{BufRead, BufReader, BufWriter, Write}; use std::path::Path; static NAMESPACES: &'static [(&'static str, &'static str)] = &[ @@ -39,8 +38,10 @@ fn main() { named_entities_to_phf( &Path::new(&manifest_dir).join("data").join("entities.json"), - &Path::new(&env::var("OUT_DIR").unwrap()).join("named_entities.rs")); + &Path::new(&env::var("OUT_DIR").unwrap()).join("named_entities.rs"), + ); + // Create a string cache for local names let local_names = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("local_names.txt"); let mut local_names_atom = string_cache_codegen::AtomType::new("LocalName", "local_name!"); for line in BufReader::new(File::open(&local_names).unwrap()).lines() { @@ -48,21 +49,40 @@ fn main() { local_names_atom.atom(&local_name); local_names_atom.atom(&local_name.to_ascii_lowercase()); } - local_names_atom.write_to(&mut generated).unwrap(); + local_names_atom + .with_macro_doc("Takes a local name as a string and returns its key in the string cache.") + .write_to(&mut generated) + .unwrap(); + // Create a string cache for namespace prefixes string_cache_codegen::AtomType::new("Prefix", "namespace_prefix!") + .with_macro_doc("Takes a namespace prefix string and returns its key in a string cache.") .atoms(NAMESPACES.iter().map(|&(prefix, _url)| prefix)) .write_to(&mut generated) .unwrap(); + // Create a string cache for namespace urls string_cache_codegen::AtomType::new("Namespace", "namespace_url!") + .with_macro_doc("Takes a namespace url string and returns its key in a string cache.") .atoms(NAMESPACES.iter().map(|&(_prefix, url)| url)) .write_to(&mut generated) .unwrap(); - writeln!(generated, "#[macro_export] macro_rules! ns {{").unwrap(); + writeln!( + generated, + r#" + /// Maps the input of `namespace_prefix!` to the output of `namespace_url!`. + #[macro_export] macro_rules! ns {{ + "# + ) + .unwrap(); for &(prefix, url) in NAMESPACES { - writeln!(generated, "({}) => {{ namespace_url!({:?}) }};", prefix, url).unwrap(); + writeln!( + generated, + "({}) => {{ namespace_url!({:?}) }};", + prefix, url + ) + .unwrap(); } writeln!(generated, "}}").unwrap(); } @@ -75,17 +95,26 @@ fn named_entities_to_phf(from: &Path, to: &Path) { //characters: String, // Present in the file but we don't need it } - let entities: HashMap<String, CharRef> - = serde_json::from_reader(&mut File::open(from).unwrap()).unwrap(); - let mut entities: HashMap<&str, (u32, u32)> = entities.iter().map(|(name, char_ref)| { - assert!(name.starts_with("&")); - assert!(char_ref.codepoints.len() <= 2); - (&name[1..], (char_ref.codepoints[0], *char_ref.codepoints.get(1).unwrap_or(&0))) - }).collect(); + let entities: HashMap<String, CharRef> = + serde_json::from_reader(&mut File::open(from).unwrap()).unwrap(); + let mut entities: HashMap<&str, (u32, u32)> = entities + .iter() + .map(|(name, char_ref)| { + assert!(name.starts_with("&")); + assert!(char_ref.codepoints.len() <= 2); + ( + &name[1..], + ( + char_ref.codepoints[0], + *char_ref.codepoints.get(1).unwrap_or(&0), + ), + ) + }) + .collect(); // Add every missing prefix of those keys, mapping to NULL characters. for key in entities.keys().cloned().collect::<Vec<_>>() { - for n in 1 .. key.len() { + for n in 1..key.len() { entities.entry(&key[..n]).or_insert((0, 0)); } } @@ -97,7 +126,9 @@ fn named_entities_to_phf(from: &Path, to: &Path) { } let mut file = File::create(to).unwrap(); - writeln!(&mut file, r#" + writeln!( + &mut file, + r#" /// A map of entity names to their codepoints. The second codepoint will /// be 0 if the entity contains a single codepoint. Entities have their preceeding '&' removed. /// @@ -108,8 +139,14 @@ fn named_entities_to_phf(from: &Path, to: &Path) { /// /// assert_eq!(NAMED_ENTITIES.get("gt;").unwrap(), &(62, 0)); /// ``` -"#).unwrap(); - write!(&mut file, "pub static NAMED_ENTITIES: Map<&'static str, (u32, u32)> = ").unwrap(); +"# + ) + .unwrap(); + write!( + &mut file, + "pub static NAMED_ENTITIES: Map<&'static str, (u32, u32)> = " + ) + .unwrap(); phf_map.build(&mut file).unwrap(); write!(&mut file, ";\n").unwrap(); } diff --git a/vendor/markup5ever/data/mod.rs b/vendor/markup5ever/data/mod.rs index 231b756220..fa839ba8ac 100644 --- a/vendor/markup5ever/data/mod.rs +++ b/vendor/markup5ever/data/mod.rs @@ -13,14 +13,38 @@ use phf::Map; /// (U+0080 through U+009F) with these characters, based on Windows 8-bit /// codepages. pub static C1_REPLACEMENTS: [Option<char>; 32] = [ - Some('\u{20ac}'), None, Some('\u{201a}'), Some('\u{0192}'), - Some('\u{201e}'), Some('\u{2026}'), Some('\u{2020}'), Some('\u{2021}'), - Some('\u{02c6}'), Some('\u{2030}'), Some('\u{0160}'), Some('\u{2039}'), - Some('\u{0152}'), None, Some('\u{017d}'), None, - None, Some('\u{2018}'), Some('\u{2019}'), Some('\u{201c}'), - Some('\u{201d}'), Some('\u{2022}'), Some('\u{2013}'), Some('\u{2014}'), - Some('\u{02dc}'), Some('\u{2122}'), Some('\u{0161}'), Some('\u{203a}'), - Some('\u{0153}'), None, Some('\u{017e}'), Some('\u{0178}'), + Some('\u{20ac}'), + None, + Some('\u{201a}'), + Some('\u{0192}'), + Some('\u{201e}'), + Some('\u{2026}'), + Some('\u{2020}'), + Some('\u{2021}'), + Some('\u{02c6}'), + Some('\u{2030}'), + Some('\u{0160}'), + Some('\u{2039}'), + Some('\u{0152}'), + None, + Some('\u{017d}'), + None, + None, + Some('\u{2018}'), + Some('\u{2019}'), + Some('\u{201c}'), + Some('\u{201d}'), + Some('\u{2022}'), + Some('\u{2013}'), + Some('\u{2014}'), + Some('\u{02dc}'), + Some('\u{2122}'), + Some('\u{0161}'), + Some('\u{203a}'), + Some('\u{0153}'), + None, + Some('\u{017e}'), + Some('\u{0178}'), ]; include!(concat!(env!("OUT_DIR"), "/named_entities.rs")); diff --git a/vendor/markup5ever/interface/mod.rs b/vendor/markup5ever/interface/mod.rs index 381b90b046..9a43065b09 100644 --- a/vendor/markup5ever/interface/mod.rs +++ b/vendor/markup5ever/interface/mod.rs @@ -6,16 +6,19 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Types for tag and attribute names, and tree-builder functionality. use std::fmt; use tendril::StrTendril; -use super::{LocalName, Prefix, Namespace}; -pub use self::tree_builder::{NodeOrText, AppendNode, AppendText, create_element, ElementFlags}; -pub use self::tree_builder::{QuirksMode, Quirks, LimitedQuirks, NoQuirks}; -pub use self::tree_builder::{TreeSink, Tracer, NextParserState}; +pub use self::tree_builder::{create_element, AppendNode, AppendText, ElementFlags, NodeOrText}; +pub use self::tree_builder::{LimitedQuirks, NoQuirks, Quirks, QuirksMode}; +pub use self::tree_builder::{NextParserState, Tracer, TreeSink}; +use super::{LocalName, Namespace, Prefix}; -/// https://www.w3.org/TR/REC-xml-names/#dt-expname +/// An [expanded name], containing the tag and the namespace. +/// +/// [expanded name]: https://www.w3.org/TR/REC-xml-names/#dt-expname #[derive(Copy, Clone, Eq, Hash)] pub struct ExpandedName<'a> { pub ns: &'a Namespace, @@ -38,6 +41,24 @@ impl<'a> fmt::Debug for ExpandedName<'a> { } } +/// Helper to quickly create an expanded name. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate markup5ever; +/// +/// # fn main() { +/// use markup5ever::ExpandedName; +/// +/// assert_eq!( +/// expanded_name!("", "div"), +/// ExpandedName { +/// ns: &ns!(), +/// local: &local_name!("div") +/// } +/// ) +/// # } #[macro_export] macro_rules! expanded_name { ("", $local: tt) => { @@ -51,18 +72,16 @@ macro_rules! expanded_name { ns: &ns!($ns), local: &local_name!($local), } - } + }; } pub mod tree_builder; -/// A name with a namespace. -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)] -/// Fully qualified name. Used to depict names of tags and attributes. +/// A fully qualified name (with a namespace), used to depict names of tags and attributes. /// -/// Used to differentiate between similar XML fragments. For example: +/// Namespaces can be used to differentiate between similar XML fragments. For example: /// -/// ```ignore +/// ```text /// // HTML /// <table> /// <tr> @@ -82,33 +101,190 @@ pub mod tree_builder; /// Without XML namespaces, we can't use those two fragments in the same document /// at the same time. However if we declare a namespace we could instead say: /// -/// ```ignore +/// ```text +/// /// // Furniture XML -/// <furn:table> +/// <furn:table xmlns:furn="https://furniture.rs"> /// <furn:name>African Coffee Table</furn:name> /// <furn:width>80</furn:width> /// <furn:length>120</furn:length> /// </furn:table> /// ``` /// -/// and bind it to a different name. +/// and bind the prefix `furn` to a different namespace. /// /// For this reason we parse names that contain a colon in the following way: /// -/// ```ignore +/// ```text /// <furn:table> /// | | /// | +- local name /// | -/// prefix (when resolved gives namespace_url) +/// prefix (when resolved gives namespace_url `https://furniture.rs`) /// ``` +/// +/// NOTE: `Prefix`, `LocalName` and `Prefix` are all derivative of +/// `string_cache::atom::Atom` and `Atom` implements `Deref<str>`. +/// +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)] +#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))] pub struct QualName { + /// The prefix of qualified (e.g. `furn` in `<furn:table>` above). + /// Optional (since some namespaces can be empty or inferred), and + /// only useful for namespace resolution (since different prefix + /// can still resolve to same namespace) + /// + /// ``` + /// + /// # fn main() { + /// use markup5ever::{QualName, Namespace, LocalName, Prefix}; + /// + /// let qual = QualName::new( + /// Some(Prefix::from("furn")), + /// Namespace::from("https://furniture.rs"), + /// LocalName::from("table"), + /// ); + /// + /// assert_eq!("furn", &qual.prefix.unwrap()); + /// + /// # } + /// ``` pub prefix: Option<Prefix>, + /// The namespace after resolution (e.g. `https://furniture.rs` in example above). + /// + /// ``` + /// # use markup5ever::{QualName, Namespace, LocalName, Prefix}; + /// + /// # fn main() { + /// # let qual = QualName::new( + /// # Some(Prefix::from("furn")), + /// # Namespace::from("https://furniture.rs"), + /// # LocalName::from("table"), + /// # ); + /// + /// assert_eq!("https://furniture.rs", &qual.ns); + /// # } + /// ``` + /// + /// When matching namespaces used by HTML we can use `ns!` macro. + /// Although keep in mind that ns! macro only works with namespaces + /// that are present in HTML spec (like `html`, `xmlns`, `svg`, etc.). + /// + /// ``` + /// #[macro_use] extern crate markup5ever; + /// + /// # use markup5ever::{QualName, Namespace, LocalName, Prefix}; + /// + /// let html_table = QualName::new( + /// None, + /// ns!(html), + /// LocalName::from("table"), + /// ); + /// + /// assert!( + /// match html_table.ns { + /// ns!(html) => true, + /// _ => false, + /// } + /// ); + /// + /// ``` pub ns: Namespace, + /// The local name (e.g. `table` in `<furn:table>` above). + /// + /// ``` + /// # use markup5ever::{QualName, Namespace, LocalName, Prefix}; + /// + /// # fn main() { + /// # let qual = QualName::new( + /// # Some(Prefix::from("furn")), + /// # Namespace::from("https://furniture.rs"), + /// # LocalName::from("table"), + /// # ); + /// + /// assert_eq!("table", &qual.local); + /// # } + /// ``` + /// When matching local name we can also use the `local_name!` macro: + /// + /// ``` + /// #[macro_use] extern crate markup5ever; + /// + /// # use markup5ever::{QualName, Namespace, LocalName, Prefix}; + /// + /// # let qual = QualName::new( + /// # Some(Prefix::from("furn")), + /// # Namespace::from("https://furniture.rs"), + /// # LocalName::from("table"), + /// # ); + /// + /// // Initialize qual to furniture example + /// + /// assert!( + /// match qual.local { + /// local_name!("table") => true, + /// _ => false, + /// } + /// ); + /// + /// ``` pub local: LocalName, } impl QualName { + /// Basic constructor function. + /// + /// First let's try it for the following example where `QualName` + /// is defined as: + /// ```text + /// <furn:table> <!-- namespace url is https://furniture.rs --> + /// ``` + /// + /// Given this definition, we can define `QualName` using strings. + /// + /// ``` + /// use markup5ever::{QualName, Namespace, LocalName, Prefix}; + /// + /// # fn main() { + /// let qual_name = QualName::new( + /// Some(Prefix::from("furn")), + /// Namespace::from("https://furniture.rs"), + /// LocalName::from("table"), + /// ); + /// # } + /// ``` + /// + /// If we were instead to construct this element instead: + /// + /// ```text + /// + /// <table> + /// ^^^^^---- no prefix and thus default html namespace + /// + /// ``` + /// + /// Or could define it using macros, like so: + /// + /// ``` + /// #[macro_use] extern crate markup5ever; + /// use markup5ever::{QualName, Namespace, LocalName, Prefix}; + /// + /// # fn main() { + /// let qual_name = QualName::new( + /// None, + /// ns!(html), + /// local_name!("table") + /// ); + /// # } + /// ``` + /// + /// Let's analyse the above example. + /// Since we have no prefix its value is None. Second we have html namespace. + /// In html5ever html namespaces are supported out of the box, + /// we can write `ns!(html)` instead of typing `Namespace::from("http://www.w3.org/1999/xhtml")`. + /// Local name is also one of the HTML elements local names, so can + /// use `local_name!("table")` macro. + /// #[inline] pub fn new(prefix: Option<Prefix>, ns: Namespace, local: LocalName) -> QualName { QualName { @@ -118,16 +294,36 @@ impl QualName { } } + /// Take a reference of `self` as an `ExpandedName`, dropping the unresolved prefix. + /// + /// In XML and HTML prefixes are only used to extract the relevant namespace URI. + /// Expanded name only contains resolved namespace and tag name, which are only + /// relevant parts of an XML or HTML tag and attribute name respectively. + /// + /// In lieu of our XML Namespace example + /// + /// ```text + /// <furn:table> <!-- namespace url is https://furniture.rs --> + /// ``` + /// For it the expanded name would become roughly equivalent to: + /// + /// ```text + /// ExpandedName { + /// ns: "https://furniture.rs", + /// local: "table", + /// } + /// ``` + /// #[inline] pub fn expanded(&self) -> ExpandedName { ExpandedName { ns: &self.ns, - local: &self.local + local: &self.local, } } } -/// A tag attribute. +/// A tag attribute, e.g. `class="test"` in `<div class="test" ...>`. /// /// The namespace on the attribute name is almost always ns!(""). /// The tokenizer creates all attributes this way, but the tree @@ -135,24 +331,31 @@ impl QualName { /// content (MathML, SVG). #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)] pub struct Attribute { + /// The name of the attribute (e.g. the `class` in `<div class="test">`) pub name: QualName, + /// The value of the attribute (e.g. the `"test"` in `<div class="test">`) pub value: StrTendril, } - #[cfg(test)] mod tests { use super::Namespace; #[test] fn ns_macro() { - assert_eq!(ns!(), Namespace::from("")); + assert_eq!(ns!(), Namespace::from("")); - assert_eq!(ns!(html), Namespace::from("http://www.w3.org/1999/xhtml")); - assert_eq!(ns!(xml), Namespace::from("http://www.w3.org/XML/1998/namespace")); - assert_eq!(ns!(xmlns), Namespace::from("http://www.w3.org/2000/xmlns/")); - assert_eq!(ns!(xlink), Namespace::from("http://www.w3.org/1999/xlink")); - assert_eq!(ns!(svg), Namespace::from("http://www.w3.org/2000/svg")); - assert_eq!(ns!(mathml), Namespace::from("http://www.w3.org/1998/Math/MathML")); + assert_eq!(ns!(html), Namespace::from("http://www.w3.org/1999/xhtml")); + assert_eq!( + ns!(xml), + Namespace::from("http://www.w3.org/XML/1998/namespace") + ); + assert_eq!(ns!(xmlns), Namespace::from("http://www.w3.org/2000/xmlns/")); + assert_eq!(ns!(xlink), Namespace::from("http://www.w3.org/1999/xlink")); + assert_eq!(ns!(svg), Namespace::from("http://www.w3.org/2000/svg")); + assert_eq!( + ns!(mathml), + Namespace::from("http://www.w3.org/1998/Math/MathML") + ); } } diff --git a/vendor/markup5ever/interface/tree_builder.rs b/vendor/markup5ever/interface/tree_builder.rs index 206eaca7a7..562a254e05 100644 --- a/vendor/markup5ever/interface/tree_builder.rs +++ b/vendor/markup5ever/interface/tree_builder.rs @@ -7,18 +7,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/// Something which can be inserted into the DOM. -/// -/// Adjacent sibling text nodes are merged into a single node, so -/// the sink may not want to allocate a `Handle` for each. +//! This module contains functionality for managing the DOM, including adding/removing nodes. +//! +//! It can be used by a parser to create the DOM graph structure in memory. -#[allow(unused_imports)] use std::ascii::AsciiExt; +use interface::{Attribute, ExpandedName, QualName}; use std::borrow::Cow; use tendril::StrTendril; -use interface::{QualName, ExpandedName, Attribute}; pub use self::NodeOrText::{AppendNode, AppendText}; -pub use self::QuirksMode::{Quirks, LimitedQuirks, NoQuirks}; +pub use self::QuirksMode::{LimitedQuirks, NoQuirks, Quirks}; /// Something which can be inserted into the DOM. /// @@ -29,11 +27,17 @@ pub enum NodeOrText<Handle> { AppendText(StrTendril), } -/// A document's quirks mode. +/// A document's quirks mode, for compatibility with old browsers. See [quirks mode on wikipedia] +/// for more information. +/// +/// [quirks mode on wikipedia]: https://en.wikipedia.org/wiki/Quirks_mode #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] pub enum QuirksMode { + /// Full quirks mode Quirks, + /// Almost standards mode LimitedQuirks, + /// Standards mode NoQuirks, } @@ -48,43 +52,82 @@ pub enum NextParserState { Continue, } +/// Special properties of an element, useful for tagging elements with this information. #[derive(Default)] pub struct ElementFlags { /// A document fragment should be created, associated with the element, - /// and returned in TreeSink::get_template_contents + /// and returned in TreeSink::get_template_contents. + /// + /// See [template-contents in the whatwg spec][whatwg template-contents]. /// - /// https://html.spec.whatwg.org/multipage/#template-contents + /// [whatwg template-contents]: https://html.spec.whatwg.org/multipage/#template-contents pub template: bool, /// This boolean should be recorded with the element and returned /// in TreeSink::is_mathml_annotation_xml_integration_point /// - /// https://html.spec.whatwg.org/multipage/#html-integration-point + /// See [html-integration-point in the whatwg spec][whatwg integration-point]. + /// + /// [whatwg integration-point]: https://html.spec.whatwg.org/multipage/#html-integration-point pub mathml_annotation_xml_integration_point: bool, - _private: () + // Prevent construction from outside module + _private: (), } +/// A constructor for an element. +/// +/// # Examples +/// +/// Create an element like `<div class="test-class-name"></div>`: +/// +/// ``` +/// # #[macro_use] extern crate markup5ever; +/// +/// # fn main() { +/// use markup5ever::{rcdom, QualName, Attribute}; +/// use markup5ever::interface::create_element; +/// +/// let mut dom = rcdom::RcDom::default(); +/// let el = create_element(&mut dom, +/// // Namespaces and localnames use precomputed interned strings for +/// // speed. Use the macros ns! and local_name! to fetch them. +/// QualName::new(None, ns!(), local_name!("div")), +/// vec![ +/// Attribute { +/// name: QualName::new(None, ns!(), local_name!("class")), +/// // In real scenarios, you would use a view onto an existing +/// // string if possible to avoid allocation. Tendrils have utilities +/// // for avoiding allocation & copying wherever possible. +/// value: String::from("test-class-name").into() +/// } +/// ]); +/// # } +/// +/// ``` pub fn create_element<Sink>(sink: &mut Sink, name: QualName, attrs: Vec<Attribute>) -> Sink::Handle -where Sink: TreeSink { +where + Sink: TreeSink, +{ let mut flags = ElementFlags::default(); match name.expanded() { - expanded_name!(html "template") => { - flags.template = true - } + expanded_name!(html "template") => flags.template = true, expanded_name!(mathml "annotation-xml") => { flags.mathml_annotation_xml_integration_point = attrs.iter().any(|attr| { - attr.name.expanded() == expanded_name!("", "encoding") && ( - attr.value.eq_ignore_ascii_case("text/html") || - attr.value.eq_ignore_ascii_case("application/xhtml+xml") - ) + attr.name.expanded() == expanded_name!("", "encoding") && + (attr.value.eq_ignore_ascii_case("text/html") || + attr.value.eq_ignore_ascii_case("application/xhtml+xml")) }) - } - _ => {} + }, + _ => {}, } sink.create_element(name, attrs, flags) } +/// Methods a parser can use to create the DOM. The DOM provider implements this trait. +/// +/// Having this as a trait potentially allows multiple implementations of the DOM to be used with +/// the same parser. pub trait TreeSink { /// `Handle` is a reference to a DOM node. The tree builder requires /// that a `Handle` implements `Clone` to get another reference to @@ -94,14 +137,14 @@ pub trait TreeSink { /// The overall result of parsing. /// /// This should default to Self, but default associated types are not stable yet. - /// (https://github.com/rust-lang/rust/issues/29661) + /// [rust-lang/rust#29661](https://github.com/rust-lang/rust/issues/29661) type Output; /// Consume this sink and return the overall result of parsing. /// /// TODO:This should default to `fn finish(self) -> Self::Output { self }`, /// but default associated types are not stable yet. - /// (https://github.com/rust-lang/rust/issues/29661) + /// [rust-lang/rust#29661](https://github.com/rust-lang/rust/issues/29661) fn finish(self) -> Self::Output; /// Signal a parse error. @@ -122,9 +165,15 @@ pub trait TreeSink { /// an associated document fragment called the "template contents" should /// also be created. Later calls to self.get_template_contents() with that /// given element return it. - /// https://html.spec.whatwg.org/multipage/#the-template-element - fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags) - -> Self::Handle; + /// See [the template element in the whatwg spec][whatwg template]. + /// + /// [whatwg template]: https://html.spec.whatwg.org/multipage/#the-template-element + fn create_element( + &mut self, + name: QualName, + attrs: Vec<Attribute>, + flags: ElementFlags, + ) -> Self::Handle; /// Create a comment node. fn create_comment(&mut self, text: StrTendril) -> Self::Handle; @@ -142,16 +191,20 @@ pub trait TreeSink { /// When the insertion point is decided by the existence of a parent node of the /// element, we consider both possibilities and send the element which will be used /// if a parent node exists, along with the element to be used if there isn't one. - fn append_based_on_parent_node(&mut self, + fn append_based_on_parent_node( + &mut self, element: &Self::Handle, prev_element: &Self::Handle, - child: NodeOrText<Self::Handle>); + child: NodeOrText<Self::Handle>, + ); /// Append a `DOCTYPE` element to the `Document` node. - fn append_doctype_to_document(&mut self, - name: StrTendril, - public_id: StrTendril, - system_id: StrTendril); + fn append_doctype_to_document( + &mut self, + name: StrTendril, + public_id: StrTendril, + system_id: StrTendril, + ); /// Mark a HTML `<script>` as "already started". fn mark_script_already_started(&mut self, _node: &Self::Handle) {} @@ -178,9 +231,7 @@ pub trait TreeSink { /// be merged, as in the behavior of `append`. /// /// NB: `new_node` may have an old parent, from which it should be removed. - fn append_before_sibling(&mut self, - sibling: &Self::Handle, - new_node: NodeOrText<Self::Handle>); + fn append_before_sibling(&mut self, sibling: &Self::Handle, new_node: NodeOrText<Self::Handle>); /// Add each attribute to the given element, if no attribute with that name /// already exists. The tree builder promises this will never be called @@ -188,10 +239,13 @@ pub trait TreeSink { fn add_attrs_if_missing(&mut self, target: &Self::Handle, attrs: Vec<Attribute>); /// Associate the given form-associatable element with the form element - fn associate_with_form(&mut self, + fn associate_with_form( + &mut self, _target: &Self::Handle, _form: &Self::Handle, - _nodes: (&Self::Handle, Option<&Self::Handle>)) {} + _nodes: (&Self::Handle, Option<&Self::Handle>), + ) { + } /// Detach the given node from its parent. fn remove_from_parent(&mut self, target: &Self::Handle); diff --git a/vendor/markup5ever/lib.rs b/vendor/markup5ever/lib.rs index 8259740085..ad23562360 100644 --- a/vendor/markup5ever/lib.rs +++ b/vendor/markup5ever/lib.rs @@ -7,8 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate string_cache; +#[macro_use] +extern crate log; extern crate phf; +extern crate string_cache; pub extern crate tendril; /// Create a [`SmallCharSet`], with each space-separated number stored in the set. @@ -34,85 +36,16 @@ macro_rules! small_char_set ( ($($e:expr)+) => ( include!(concat!(env!("OUT_DIR"), "/generated.rs")); - pub mod data; -#[macro_use] pub mod interface; +#[macro_use] +pub mod interface; pub mod rcdom; pub mod serialize; mod util { - pub mod smallcharset; pub mod buffer_queue; + pub mod smallcharset; } -pub use util::*; -pub use interface::{ExpandedName, QualName, Attribute}; +pub use interface::{Attribute, ExpandedName, QualName}; pub use util::smallcharset::SmallCharSet; - - - -#[cfg(test)] -#[allow(non_snake_case)] -mod test { - #[allow(unused_imports)] use std::ascii::AsciiExt; - use tendril::SliceExt; - - use super::util::buffer_queue::{BufferQueue, FromSet, NotFromSet}; - - #[test] - fn smoke_test() { - let mut bq = BufferQueue::new(); - assert_eq!(bq.peek(), None); - assert_eq!(bq.next(), None); - - bq.push_back("abc".to_tendril()); - assert_eq!(bq.peek(), Some('a')); - assert_eq!(bq.next(), Some('a')); - assert_eq!(bq.peek(), Some('b')); - assert_eq!(bq.peek(), Some('b')); - assert_eq!(bq.next(), Some('b')); - assert_eq!(bq.peek(), Some('c')); - assert_eq!(bq.next(), Some('c')); - assert_eq!(bq.peek(), None); - assert_eq!(bq.next(), None); - } - - #[test] - fn can_unconsume() { - let mut bq = BufferQueue::new(); - bq.push_back("abc".to_tendril()); - assert_eq!(bq.next(), Some('a')); - - bq.push_front("xy".to_tendril()); - assert_eq!(bq.next(), Some('x')); - assert_eq!(bq.next(), Some('y')); - assert_eq!(bq.next(), Some('b')); - assert_eq!(bq.next(), Some('c')); - assert_eq!(bq.next(), None); - } - - #[test] - fn can_pop_except_set() { - let mut bq = BufferQueue::new(); - bq.push_back("abc&def".to_tendril()); - let mut pop = || bq.pop_except_from(small_char_set!('&')); - assert_eq!(pop(), Some(NotFromSet("abc".to_tendril()))); - assert_eq!(pop(), Some(FromSet('&'))); - assert_eq!(pop(), Some(NotFromSet("def".to_tendril()))); - assert_eq!(pop(), None); - } - - #[test] - fn can_eat() { - // This is not very comprehensive. We rely on the tokenizer - // integration tests for more thorough testing with many - // different input buffer splits. - let mut bq = BufferQueue::new(); - bq.push_back("a".to_tendril()); - bq.push_back("bc".to_tendril()); - assert_eq!(bq.eat("abcd", u8::eq_ignore_ascii_case), None); - assert_eq!(bq.eat("ax", u8::eq_ignore_ascii_case), Some(false)); - assert_eq!(bq.eat("ab", u8::eq_ignore_ascii_case), Some(true)); - assert_eq!(bq.next(), Some('c')); - assert_eq!(bq.next(), None); - } -} +pub use util::*; diff --git a/vendor/markup5ever/local_names.txt b/vendor/markup5ever/local_names.txt index 99dd2d2ec1..d3d6cd41b0 100644 --- a/vendor/markup5ever/local_names.txt +++ b/vendor/markup5ever/local_names.txt @@ -437,6 +437,7 @@ keyPoints keySplines keyTimes keygen +kind label lambda lang @@ -556,6 +557,7 @@ multicol multiple munder munderover +muted name nargs naturalnumbers @@ -567,6 +569,8 @@ nobr noembed noframes nohref +nomodule +nonce none noresize noscript @@ -836,6 +840,7 @@ speed spreadMethod src srcdoc +srclang srcset standby start diff --git a/vendor/markup5ever/rcdom.rs b/vendor/markup5ever/rcdom.rs index bad332cdc3..420fcccbe5 100644 --- a/vendor/markup5ever/rcdom.rs +++ b/vendor/markup5ever/rcdom.rs @@ -11,32 +11,61 @@ //! //! This is sufficient as a static parse tree, but don't build a //! web browser using it. :) +//! +//! A DOM is a [tree structure] with ordered children that can be represented in an XML-like +//! format. For example, the following graph +//! +//! ```text +//! div +//! +- "text node" +//! +- span +//! ``` +//! in HTML would be serialized as +//! +//! ```html +//! <div>text node<span></span></div> +//! ``` +//! +//! See the [document object model article on wikipedia][dom wiki] for more information. +//! +//! This implementation stores the information associated with each node once, and then hands out +//! refs to children. The nodes themselves are reference-counted to avoid copying - you can create +//! a new ref and then a node will outlive the document. Nodes own their children, but only have +//! weak references to their parents. +//! +//! [tree structure]: https://en.wikipedia.org/wiki/Tree_(data_structure) +//! [dom wiki]: https://en.wikipedia.org/wiki/Document_Object_Model -use std::cell::{RefCell, Cell}; +use std::borrow::Cow; +use std::cell::{Cell, RefCell}; use std::collections::HashSet; use std::default::Default; -use std::borrow::Cow; +use std::fmt; use std::io; use std::mem; use std::rc::{Rc, Weak}; use tendril::StrTendril; +use interface::tree_builder; +use interface::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink}; +use serialize::TraversalScope; +use serialize::TraversalScope::{ChildrenOnly, IncludeNode}; +use serialize::{Serialize, Serializer}; use Attribute; use ExpandedName; use QualName; -use interface::tree_builder::{TreeSink, QuirksMode, NodeOrText, ElementFlags}; -use interface::tree_builder; -use serialize::{Serialize, Serializer}; -use serialize::TraversalScope; -use serialize::TraversalScope::{IncludeNode, ChildrenOnly}; /// The different kinds of nodes in the DOM. +#[derive(Debug)] pub enum NodeData { - /// The `Document` itself. + /// The `Document` itself - the root node of a HTML document. Document, - /// A `DOCTYPE` with name, public id, and system id. + /// A `DOCTYPE` with name, public id, and system id. See + /// [document type declaration on wikipedia][dtd wiki]. + /// + /// [dtd wiki]: https://en.wikipedia.org/wiki/Document_type_declaration Doctype { name: StrTendril, public_id: StrTendril, @@ -44,25 +73,24 @@ pub enum NodeData { }, /// A text node. - Text { - contents: RefCell<StrTendril>, - }, + Text { contents: RefCell<StrTendril> }, /// A comment. - Comment { - contents: StrTendril, - }, + Comment { contents: StrTendril }, /// An element with attributes. Element { name: QualName, attrs: RefCell<Vec<Attribute>>, - /// For HTML <template> elements, the template contents - /// https://html.spec.whatwg.org/multipage/#template-contents + /// For HTML \<template\> elements, the [template contents]. + /// + /// [template contents]: https://html.spec.whatwg.org/multipage/#template-contents template_contents: Option<Handle>, - /// https://html.spec.whatwg.org/multipage/#html-integration-point + /// Whether the node is a [HTML integration point]. + /// + /// [HTML integration point]: https://html.spec.whatwg.org/multipage/#html-integration-point mathml_annotation_xml_integration_point: bool, }, @@ -81,17 +109,58 @@ pub struct Node { pub children: RefCell<Vec<Handle>>, /// Represents this node's data. pub data: NodeData, + /// Flag to control whether to free any children on destruction. + leak_children_on_drop: Cell<bool>, } impl Node { /// Create a new node from its contents - fn new(data: NodeData) -> Rc<Self> { + pub fn new(data: NodeData) -> Rc<Self> { Rc::new(Node { data: data, parent: Cell::new(None), children: RefCell::new(Vec::new()), + leak_children_on_drop: Cell::new(true), }) } + + /// Drop any child nodes remaining in this node at destruction. + /// + /// RcDom's destructor automatically drops any nodes and children that are + /// present in the document. This setting only affects nodes that are dropped + /// by manipulating the tree before RcDom's destructor runs (such as manually + /// removing children from a node after parsing is complete). + /// + /// Unsafety: due to the representation of children, this can trigger + /// stack overflow if dropping a node with a very deep tree of children. + /// This is not a recommended configuration to use when interacting with + /// arbitrary HTML content. + pub unsafe fn free_child_nodes_on_drop(&self) { + self.leak_children_on_drop.set(false); + } +} + +impl Drop for Node { + fn drop(&mut self) { + if !self.children.borrow().is_empty() { + if self.leak_children_on_drop.get() { + warn!("Dropping node with children outside of RcDom's destructor. \ + Leaking memory for {} children.", self.children.borrow().len()); + for child in mem::replace(&mut *self.children.borrow_mut(), vec![]) { + mem::forget(child); + } + } + } + } +} + +impl fmt::Debug for Node { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Node") + .field("data", &self.data) + .field("children", &self.children) + .finish() + } } /// Reference to a DOM node. @@ -113,8 +182,13 @@ fn get_parent_and_index(target: &Handle) -> Option<(Handle, usize)> { if let Some(weak) = target.parent.take() { let parent = weak.upgrade().expect("dangling weak pointer"); target.parent.set(Some(weak)); - let i = match parent.children.borrow().iter().enumerate() - .find(|&(_, child)| Rc::ptr_eq(&child, &target)) { + let i = match parent + .children + .borrow() + .iter() + .enumerate() + .find(|&(_, child)| Rc::ptr_eq(&child, &target)) + { Some((i, _)) => i, None => panic!("have parent but couldn't find in parent's children!"), }; @@ -129,7 +203,7 @@ fn append_to_existing_text(prev: &Handle, text: &str) -> bool { NodeData::Text { ref contents } => { contents.borrow_mut().push_slice(text); true - } + }, _ => false, } } @@ -153,9 +227,23 @@ pub struct RcDom { pub quirks_mode: QuirksMode, } +impl Drop for RcDom { + fn drop(&mut self) { + // Ensure that node destructors execute linearly, rather + // than recursing through a tree of arbitrary depth. + let mut to_be_processed = vec![self.document.clone()]; + while let Some(node) = to_be_processed.pop() { + to_be_processed.extend_from_slice(&*node.children.borrow()); + node.children.borrow_mut().clear(); + } + } +} + impl TreeSink for RcDom { type Output = Self; - fn finish(self) -> Self { self } + fn finish(self) -> Self { + self + } type Handle = Handle; @@ -168,7 +256,11 @@ impl TreeSink for RcDom { } fn get_template_contents(&mut self, target: &Handle) -> Handle { - if let NodeData::Element { template_contents: Some(ref contents), .. } = target.data { + if let NodeData::Element { + template_contents: Some(ref contents), + .. + } = target.data + { contents.clone() } else { panic!("not a template element!") @@ -190,7 +282,12 @@ impl TreeSink for RcDom { }; } - fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags) -> Handle { + fn create_element( + &mut self, + name: QualName, + attrs: Vec<Attribute>, + flags: ElementFlags, + ) -> Handle { Node::new(NodeData::Element { name: name, attrs: RefCell::new(attrs), @@ -208,46 +305,58 @@ impl TreeSink for RcDom { } fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> Handle { - Node::new(NodeData::ProcessingInstruction { target: target, contents: data }) + Node::new(NodeData::ProcessingInstruction { + target: target, + contents: data, + }) } fn append(&mut self, parent: &Handle, child: NodeOrText<Handle>) { // Append to an existing Text node if we have one. match child { NodeOrText::AppendText(ref text) => match parent.children.borrow().last() { - Some(h) => if append_to_existing_text(h, &text) { return; }, + Some(h) => { + if append_to_existing_text(h, &text) { + return; + } + }, _ => (), }, _ => (), } - append(&parent, match child { - NodeOrText::AppendText(text) => Node::new(NodeData::Text { contents: RefCell::new(text) }), - NodeOrText::AppendNode(node) => node - }); + append( + &parent, + match child { + NodeOrText::AppendText(text) => Node::new(NodeData::Text { + contents: RefCell::new(text), + }), + NodeOrText::AppendNode(node) => node, + }, + ); } - fn append_before_sibling(&mut self, - sibling: &Handle, - child: NodeOrText<Handle>) { + fn append_before_sibling(&mut self, sibling: &Handle, child: NodeOrText<Handle>) { let (parent, i) = get_parent_and_index(&sibling) .expect("append_before_sibling called on node without parent"); let child = match (child, i) { // No previous node. - (NodeOrText::AppendText(text), 0) => { - Node::new(NodeData::Text { contents: RefCell::new(text) }) - } + (NodeOrText::AppendText(text), 0) => Node::new(NodeData::Text { + contents: RefCell::new(text), + }), // Look for a text node before the insertion point. (NodeOrText::AppendText(text), i) => { let children = parent.children.borrow(); - let prev = &children[i-1]; + let prev = &children[i - 1]; if append_to_existing_text(prev, &text) { return; } - Node::new(NodeData::Text { contents: RefCell::new(text) }) - } + Node::new(NodeData::Text { + contents: RefCell::new(text), + }) + }, // The tree builder promises we won't have a text node after // the insertion point. @@ -262,10 +371,12 @@ impl TreeSink for RcDom { parent.children.borrow_mut().insert(i, child); } - fn append_based_on_parent_node(&mut self, + fn append_based_on_parent_node( + &mut self, element: &Self::Handle, prev_element: &Self::Handle, - child: NodeOrText<Self::Handle>) { + child: NodeOrText<Self::Handle>, + ) { let parent = element.parent.take(); let has_parent = parent.is_some(); element.parent.set(parent); @@ -277,15 +388,20 @@ impl TreeSink for RcDom { } } - fn append_doctype_to_document(&mut self, - name: StrTendril, - public_id: StrTendril, - system_id: StrTendril) { - append(&self.document, Node::new(NodeData::Doctype { - name: name, - public_id: public_id, - system_id: system_id - })); + fn append_doctype_to_document( + &mut self, + name: StrTendril, + public_id: StrTendril, + system_id: StrTendril, + ) { + append( + &self.document, + Node::new(NodeData::Doctype { + name: name, + public_id: public_id, + system_id: system_id, + }), + ); } fn add_attrs_if_missing(&mut self, target: &Handle, attrs: Vec<Attribute>) { @@ -295,11 +411,15 @@ impl TreeSink for RcDom { panic!("not an element") }; - let existing_names = - existing.iter().map(|e| e.name.clone()).collect::<HashSet<_>>(); - existing.extend(attrs.into_iter().filter(|attr| { - !existing_names.contains(&attr.name) - })); + let existing_names = existing + .iter() + .map(|e| e.name.clone()) + .collect::<HashSet<_>>(); + existing.extend( + attrs + .into_iter() + .filter(|attr| !existing_names.contains(&attr.name)), + ); } fn remove_from_parent(&mut self, target: &Handle) { @@ -311,13 +431,20 @@ impl TreeSink for RcDom { let mut new_children = new_parent.children.borrow_mut(); for child in children.iter() { let previous_parent = child.parent.replace(Some(Rc::downgrade(&new_parent))); - assert!(Rc::ptr_eq(&node, &previous_parent.unwrap().upgrade().expect("dangling weak"))) + assert!(Rc::ptr_eq( + &node, + &previous_parent.unwrap().upgrade().expect("dangling weak") + )) } new_children.extend(mem::replace(&mut *children, Vec::new())); } fn is_mathml_annotation_xml_integration_point(&self, target: &Handle) -> bool { - if let NodeData::Element { mathml_annotation_xml_integration_point, .. } = target.data { + if let NodeData::Element { + mathml_annotation_xml_integration_point, + .. + } = target.data + { mathml_annotation_xml_integration_point } else { panic!("not an element!") @@ -329,56 +456,77 @@ impl Default for RcDom { fn default() -> RcDom { RcDom { document: Node::new(NodeData::Document), - errors: vec!(), + errors: vec![], quirks_mode: tree_builder::NoQuirks, } } } +enum SerializeOp { + Open(Handle), + Close(QualName) +} + impl Serialize for Handle { fn serialize<S>(&self, serializer: &mut S, traversal_scope: TraversalScope) -> io::Result<()> - where S: Serializer { - match (&traversal_scope, &self.data) { - (_, &NodeData::Element { ref name, ref attrs, .. }) => { - if traversal_scope == IncludeNode { - try!(serializer.start_elem(name.clone(), - attrs.borrow().iter().map(|at| (&at.name, &at.value[..])))); - } - - for handle in self.children.borrow().iter() { - try!(handle.clone().serialize(serializer, IncludeNode)); - } + where + S: Serializer, + { + let mut ops = match traversal_scope { + IncludeNode => vec![SerializeOp::Open(self.clone())], + ChildrenOnly(_) => self + .children + .borrow() + .iter() + .map(|h| SerializeOp::Open(h.clone())).collect(), + }; - if traversal_scope == IncludeNode { - try!(serializer.end_elem(name.clone())); + while !ops.is_empty() { + match ops.remove(0) { + SerializeOp::Open(handle) => { + match &handle.data { + &NodeData::Element { + ref name, + ref attrs, + .. + } => { + try!(serializer.start_elem( + name.clone(), + attrs.borrow().iter().map(|at| (&at.name, &at.value[..])) + )); + + ops.insert(0, SerializeOp::Close(name.clone())); + + for child in handle.children.borrow().iter().rev() { + ops.insert(0, SerializeOp::Open(child.clone())); + } + } + + &NodeData::Doctype { ref name, .. } => serializer.write_doctype(&name)?, + + &NodeData::Text { ref contents } => { + serializer.write_text(&contents.borrow())? + } + + &NodeData::Comment { ref contents } => { + serializer.write_comment(&contents)? + }, + + &NodeData::ProcessingInstruction { + ref target, + ref contents, + } => serializer.write_processing_instruction(target, contents)?, + + &NodeData::Document => panic!("Can't serialize Document node itself"), + } } - Ok(()) - } - (&ChildrenOnly(_), &NodeData::Document) => { - for handle in self.children.borrow().iter() { - try!(handle.clone().serialize(serializer, IncludeNode)); + SerializeOp::Close(name) => { + try!(serializer.end_elem(name)); } - Ok(()) - } - - (&ChildrenOnly(_), _) => Ok(()), - - (&IncludeNode, &NodeData::Doctype { ref name, .. }) => { - serializer.write_doctype(&name) - } - (&IncludeNode, &NodeData::Text { ref contents }) => { - serializer.write_text(&contents.borrow()) - } - (&IncludeNode, &NodeData::Comment { ref contents }) => { - serializer.write_comment(&contents) - } - (&IncludeNode, &NodeData::ProcessingInstruction { ref target, ref contents }) => { - serializer.write_processing_instruction(target, contents) - }, - (&IncludeNode, &NodeData::Document) => { - panic!("Can't serialize Document node itself") } } + + Ok(()) } } diff --git a/vendor/markup5ever/serialize.rs b/vendor/markup5ever/serialize.rs index 3430d76509..00d358ce08 100644 --- a/vendor/markup5ever/serialize.rs +++ b/vendor/markup5ever/serialize.rs @@ -13,8 +13,8 @@ //! //! [processing instructions]: https://en.wikipedia.org/wiki/Processing_Instruction -use QualName; use std::io; +use QualName; //§ serializing-html-fragments /// Used as a parameter to `serialize`, telling it if we want to skip the parent. @@ -28,7 +28,7 @@ pub enum TraversalScope { /// This is used in the implementation of [`html5ever::serialize::serialize`] /// /// [`html5ever::serialize::serialize`]: ../../html5ever/serialize/fn.serialize.html - ChildrenOnly(Option<QualName>) + ChildrenOnly(Option<QualName>), } /// Types that can be serialized (according to the xml-like scheme in `Serializer`) implement this @@ -37,14 +37,16 @@ pub trait Serialize { /// Take the serializer and call its methods to serialize this type. The type will dictate /// which methods are called and with what parameters. fn serialize<S>(&self, serializer: &mut S, traversal_scope: TraversalScope) -> io::Result<()> - where S: Serializer; + where + S: Serializer; } /// Types that are capable of serializing implement this trait pub trait Serializer { /// Serialize the start of an element, for example `<div class="test">`. fn start_elem<'a, AttrIter>(&mut self, name: QualName, attrs: AttrIter) -> io::Result<()> - where AttrIter: Iterator<Item=AttrRef<'a>>; + where + AttrIter: Iterator<Item = AttrRef<'a>>; /// Serialize the end of an element, for example `</div>`. fn end_elem(&mut self, name: QualName) -> io::Result<()>; diff --git a/vendor/markup5ever/util/buffer_queue.rs b/vendor/markup5ever/util/buffer_queue.rs index ab32961a5c..2bb5de8311 100644 --- a/vendor/markup5ever/util/buffer_queue.rs +++ b/vendor/markup5ever/util/buffer_queue.rs @@ -18,7 +18,6 @@ //! //! [`BufferQueue`]: struct.BufferQueue.html - use std::collections::VecDeque; use tendril::StrTendril; @@ -44,6 +43,7 @@ pub enum SetResult { /// Internally it uses [`VecDeque`] and has the same complexity properties. /// /// [`VecDeque`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html +#[derive(Debug)] pub struct BufferQueue { /// Buffers to process. buffers: VecDeque<StrTendril>, @@ -92,8 +92,14 @@ impl BufferQueue { /// Look at the next available character without removing it, if the queue is not empty. pub fn peek(&self) -> Option<char> { - debug_assert!(self.buffers.iter().skip_while(|el| el.len32() != 0).next().is_none(), - "invariant \"all buffers in the queue are non-empty\" failed"); + debug_assert!( + self.buffers + .iter() + .skip_while(|el| el.len32() != 0) + .next() + .is_none(), + "invariant \"all buffers in the queue are non-empty\" failed" + ); self.buffers.front().map(|b| b.chars().next().unwrap()) } @@ -106,7 +112,7 @@ impl BufferQueue { Some(buf) => { let c = buf.pop_front_char().expect("empty buffer in queue"); (Some(c), buf.is_empty()) - } + }, }; if now_empty { @@ -159,7 +165,7 @@ impl BufferQueue { let c = buf.pop_front_char().expect("empty buffer in queue"); (Some(FromSet(c)), buf.is_empty()) } - } + }, }; // Unborrow self for this part. @@ -207,7 +213,7 @@ impl BufferQueue { let ref buf = self.buffers[buffers_exhausted]; if !eq(&buf.as_bytes()[consumed_from_last], &pattern_byte) { - return Some(false) + return Some(false); } consumed_from_last += 1; @@ -218,7 +224,7 @@ impl BufferQueue { } // We have a match. Commit changes to the BufferQueue. - for _ in 0 .. buffers_exhausted { + for _ in 0..buffers_exhausted { self.buffers.pop_front(); } @@ -230,3 +236,70 @@ impl BufferQueue { Some(true) } } + +#[cfg(test)] +#[allow(non_snake_case)] +mod test { + use tendril::SliceExt; + + use super::BufferQueue; + use super::SetResult::{FromSet, NotFromSet}; + + #[test] + fn smoke_test() { + let mut bq = BufferQueue::new(); + assert_eq!(bq.peek(), None); + assert_eq!(bq.next(), None); + + bq.push_back("abc".to_tendril()); + assert_eq!(bq.peek(), Some('a')); + assert_eq!(bq.next(), Some('a')); + assert_eq!(bq.peek(), Some('b')); + assert_eq!(bq.peek(), Some('b')); + assert_eq!(bq.next(), Some('b')); + assert_eq!(bq.peek(), Some('c')); + assert_eq!(bq.next(), Some('c')); + assert_eq!(bq.peek(), None); + assert_eq!(bq.next(), None); + } + + #[test] + fn can_unconsume() { + let mut bq = BufferQueue::new(); + bq.push_back("abc".to_tendril()); + assert_eq!(bq.next(), Some('a')); + + bq.push_front("xy".to_tendril()); + assert_eq!(bq.next(), Some('x')); + assert_eq!(bq.next(), Some('y')); + assert_eq!(bq.next(), Some('b')); + assert_eq!(bq.next(), Some('c')); + assert_eq!(bq.next(), None); + } + + #[test] + fn can_pop_except_set() { + let mut bq = BufferQueue::new(); + bq.push_back("abc&def".to_tendril()); + let mut pop = || bq.pop_except_from(small_char_set!('&')); + assert_eq!(pop(), Some(NotFromSet("abc".to_tendril()))); + assert_eq!(pop(), Some(FromSet('&'))); + assert_eq!(pop(), Some(NotFromSet("def".to_tendril()))); + assert_eq!(pop(), None); + } + + #[test] + fn can_eat() { + // This is not very comprehensive. We rely on the tokenizer + // integration tests for more thorough testing with many + // different input buffer splits. + let mut bq = BufferQueue::new(); + bq.push_back("a".to_tendril()); + bq.push_back("bc".to_tendril()); + assert_eq!(bq.eat("abcd", u8::eq_ignore_ascii_case), None); + assert_eq!(bq.eat("ax", u8::eq_ignore_ascii_case), Some(false)); + assert_eq!(bq.eat("ab", u8::eq_ignore_ascii_case), Some(true)); + assert_eq!(bq.next(), Some('c')); + assert_eq!(bq.next(), None); + } +} diff --git a/vendor/markup5ever/util/smallcharset.rs b/vendor/markup5ever/util/smallcharset.rs index 6f85ce3e58..957dad7303 100644 --- a/vendor/markup5ever/util/smallcharset.rs +++ b/vendor/markup5ever/util/smallcharset.rs @@ -11,7 +11,6 @@ //! //! [`SmallCharSet`]: struct.SmallCharSet.html - /// Represents a set of "small characters", those with Unicode scalar /// values less than 64. /// @@ -76,8 +75,8 @@ mod test { #[test] fn nonmember_prefix() { for &c in ['&', '\0'].iter() { - for x in 0 .. 48u32 { - for y in 0 .. 48u32 { + for x in 0..48u32 { + for y in 0..48u32 { let mut s = repeat("x").take(x as usize).collect::<String>(); s.push(c); s.push_str(&repeat("x").take(y as usize).collect::<String>()); diff --git a/vendor/mdbook/.cargo-checksum.json b/vendor/mdbook/.cargo-checksum.json index 3309765133..a22fa15a65 100644 --- a/vendor/mdbook/.cargo-checksum.json +++ b/vendor/mdbook/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"0137d8c648b9500dda658f2bdde230f989f99897e644bc3006f3134df26d2146","Cargo.toml":"00216281e55d79191e534fdf488ce28b0e3ec4de2bccb9b9383ff20a8abacf2d","LICENSE":"af175b9d96ee93c21a036152e1b905b0b95304d4ae8c2c921c7609100ba8df7e","README.md":"38a7358b5f780ad15bd103a59e28d092f9b39032541f71ca4d1c6d97b873857c","appveyor.yml":"fc70f748d4e68df852bd37599b992ec6c8ea65067928795742e485cc19d5f747","ci/before_deploy.sh":"4f01a05883c02ffb77380107f0f6a360edcf613dbb3e69a2790d99895d24e6d6","examples/de-emphasize.rs":"214cb776f3e9fda2978cd708ae24e5c65fe9968bffb42bd1a9890c8e2f1723b9","examples/nop-preprocessor.rs":"eaab470ef7d9e027a60fb4f507d8a2d7c09003e781b7de2284a7af39d8cc50b7","release.toml":"25e91966f4a77515244adf5775d638590916c550f9d25bba6024d629b71840e8","src/book/book.rs":"5f850bc4e0b91252e6786cd71128006dcde119cafdea9dbe921491522171e1d7","src/book/init.rs":"d40c49f6646a5fabf3aa91d2168f1b6cfbd9243aeae97745e1f4a911c309bbf7","src/book/mod.rs":"5d7b88329da35b139b9cecba50190e5529f3c143a6848d2d766e7913ac0316e2","src/book/summary.rs":"ff663454f544072dc9b5dd6a37e37262f1ec7c623a23d248a3f194cea8536ff5","src/cmd/build.rs":"050afab40dcdb4cdd4fadaef1f2c901ea4b30c33850e73eaacc3f98fd651a9f7","src/cmd/clean.rs":"85830c3e7df651ab81db5fc0f97b867cb460f2cb10c1c0105ce1292eeee12c6f","src/cmd/init.rs":"f5c7b28e44b2c19420259025c4f5fa2b38b55df57409834a23639b1bff410f2e","src/cmd/mod.rs":"29116e5ca90e916a5f4ce62581a29508670ef184ec3e20569e2ad90b57472abe","src/cmd/serve.rs":"374f831bed4ddc68b085d75e8eb692f85195ecd59dd78be59b9710077d09a8a4","src/cmd/test.rs":"a7179aa4fe516297a7cf0126ba441828bb56a09d56f501f4653463c563fd586d","src/cmd/watch.rs":"c81baad03508b33393191cabc823ec2fe74d3ca8e04adb117355574da7c56241","src/config.rs":"733faf9c735bfddddf6a7b94db960c7a56613a6c9a207ac569402e2222505a53","src/lib.rs":"88ec0185c20c790a0355d555d3fce7b646ef219149ede22972b128f344801c3c","src/main.rs":"7a117c580d789620cea5b63f5e04dc8314d901d0886dc78c25aa22e2d197deea","src/preprocess/cmd.rs":"56be6a0a09b079135d2d236a8d5ebdf68d4bab10cd8110708b34252a4df9e98a","src/preprocess/index.rs":"d26188520dabc8f1367a6f019d62e8ef32a7318647b2fd61ca820fea5ec1e84c","src/preprocess/links.rs":"152ac786348d7e583fcead3e9c9a3633181ff4192fe4401be4c592ee28e3351d","src/preprocess/mod.rs":"bc87f1b26c46ddb37d6a28f386754000d8d4cc4df13584480b3089f98903d3bc","src/renderer/html_handlebars/hbs_renderer.rs":"f0a549e10c84de5316e93ac12fb26dd9e05ec872fcf752a72f64efe2126c60b1","src/renderer/html_handlebars/helpers/mod.rs":"d83520feecce350b03b7ffaa9f34d6db2fe7316a46562be694b8eef537124191","src/renderer/html_handlebars/helpers/navigation.rs":"17b01112b5e25dae52b044d93433a3c6026983ab6a82a8c855db593d292bb97c","src/renderer/html_handlebars/helpers/theme.rs":"37a9627457e887d9d805a721fdc23d86a7b3c2efee7f7b2d65e4608280b9a867","src/renderer/html_handlebars/helpers/toc.rs":"97a34a09db9dafd33a04355178bb4497db3618728e339909acb49e3913bb78b9","src/renderer/html_handlebars/mod.rs":"b6be4801cf49040edc9dad216ed12c26dce87e2dc4724ee24729e4a8b67734b0","src/renderer/html_handlebars/search.rs":"2963da5e6e0bbbb83911600c522f153ca9120fd53e4355de6a932e473728aed4","src/renderer/mod.rs":"f17c9a56c1756df51102287ec94321c745764962b3ae3d59b3aa4b98cd37e099","src/theme/FontAwesome/css/font-awesome.min.css":"799aeb25cc0373fdee0e1b1db7ad6c2f6a0e058dfadaa3379689f583213190bd","src/theme/FontAwesome/fonts/FontAwesome.otf":"444dd4366615ffc4a16d012b2fa90137065d3ccb410fa6fd5e4ddd7b5e4ffcd5","src/theme/FontAwesome/fonts/fontawesome-webfont.eot":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","src/theme/FontAwesome/fonts/fontawesome-webfont.svg":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","src/theme/FontAwesome/fonts/fontawesome-webfont.ttf":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","src/theme/FontAwesome/fonts/fontawesome-webfont.woff":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","src/theme/FontAwesome/fonts/fontawesome-webfont.woff2":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","src/theme/ayu-highlight.css":"0f5744347d66081ac6eabb1d10e4971004ff15fc76bd8116b09ae436bc3920c6","src/theme/book.js":"2ee70e623b9c2c88458c00c30d4626d072f452c7f53c3ac32123ac16ae3ffa35","src/theme/clipboard.min.js":"125d1f1220f760e33bb88559cedc90ce66db3e58048f4a09571456ce2521e141","src/theme/css/chrome.css":"d633c3718131e495a07ba905f088555575ddda98514d21ed267d18d849894def","src/theme/css/general.css":"14427af18776261ec1c857faffe42c118b7535804ded981c49b3ab0526fdcdea","src/theme/css/print.css":"a4278dff9af38765eb9d344aa56dcc652ac79c73afc408385b62a4b611b89c14","src/theme/css/variables.css":"11f1ef43987922056ebcd63eb0bbea7a45dfdc5b10706b7011f585ecf6ba7c0f","src/theme/favicon.png":"8114d1fc74f4b5621ad9afde7746ed9cf7e420be317a6e29023d2298d58aa15b","src/theme/header.hbs":"1fd27c9ccd016060dc4d6e77f12bf58b26e7c604aebe2577a67097f95a3de70a","src/theme/highlight.css":"61435026e22c7901be6c8ceadf471f2051d380872e8c505c2f12f4ef5f0ca8ff","src/theme/highlight.js":"f2bea9a2c2225104635af594b0eb20e9d57b975ca1f86753fccb03dcbf36566f","src/theme/index.hbs":"9c61fbd9e1277f621637fdd6b13e2f40987eae535bb34138141a38430125ce63","src/theme/mod.rs":"e7b0bee330e44d01111244cfa5a52692b244925949ea33211fd32e68980d6b75","src/theme/playpen_editor/ace.js":"2c0dc1bf802b5fa7d0e49440723ecfda5ff6c86a755baaa832ae9ae019526f63","src/theme/playpen_editor/editor.js":"21f156b6cfa34492e9984256c0e1356a3ef7fc51b5c2737531f6081f2599f935","src/theme/playpen_editor/mod.rs":"0c582869eac4519049b333187ad5cfd22366c46143dd90eced93f85b99653901","src/theme/playpen_editor/mode-rust.js":"4f39534827f7ef60901589f0f56922658f8d389ced4b258050bd229a19bc43ac","src/theme/playpen_editor/theme-dawn.js":"f292ee1761e1df2fec277ea04e64520d4d4a7d4555dabae1baa0b31862f31168","src/theme/playpen_editor/theme-tomorrow_night.js":"3076be9f73040544fab6a9e77f8e572e45cef912666a7215a4a1210819858e70","src/theme/searcher/elasticlunr.min.js":"ef4e11c157b1e2e89782d30bd726f2d5ff7834ea5e26ad02474325f8b1f126c9","src/theme/searcher/mark.min.js":"09e88c2cfaf23ea8a37b5681433eafea97033af632ecc948c8c1ee9944647743","src/theme/searcher/mod.rs":"cc8fbdc923d8d817c72bc97a178e57bdf8a3f5cfcba595eb4eee19bcbb26c67c","src/theme/searcher/searcher.js":"cb2e829c9a1efb9063231e0139abd7a1070306b26e9a0e5da83376f742995f06","src/theme/tomorrow-night.css":"c914fd853acc9b53301a97948476de8a8ffd3e40f5bbd4f5d62ff42819558b82","src/utils/fs.rs":"5b824d54294c99bde9842b432cfe1cb8635d4bebe0ac81a153800c0478a1bdc0","src/utils/mod.rs":"90202f5310e3466a5c90eb449ee6242c3cafbc323ad8d564a1454f9a830d9fc8","src/utils/string.rs":"1d5446c88d5a33093a41f9255abf2a88d763e2d746119c9d18e8e2f0a98b001b","tests/alternate_backends.rs":"bf9342fbb6bcf85f83c3be75e22df401d99b321aa0c9edaa81cd485863af68a6","tests/build_process.rs":"8693e2eb9afdb2998e19ce9fac589441e2ddb734c9656fa1ea63d53189b260c6","tests/custom_preprocessors.rs":"827f6a2e4f30c658a09ffc7e2d5de01a5fe170934e9a02d3309ef2457e161d82","tests/dummy_book/mod.rs":"d816b3f0c5febb467ccce134390b53a39cfcf51fa62cf1440f01b1a1ded562e2","tests/dummy_book/src/README.md":"2f6e578b9f31ff5e1d18ae40865355d59e56a23e02798bd8166751245ef4eb9b","tests/dummy_book/src/SUMMARY.md":"f83c69469054a61003b89d3cda9f13a5a5964c6542c594e0f7a92be95cc8ccac","tests/dummy_book/src/conclusion.md":"eca0543344979e938b43debf3d310290a628e8b7b45d3d9bec63c21e61284a4c","tests/dummy_book/src/example.rs":"3be109d6faa3c6104c8fb5e8ffdfe3eba73d0a5ed4f537685fe2cf2c36e657d0","tests/dummy_book/src/first/includes.md":"747f8f1eb4d394c1fdb773acddb7ffdc641e3ad71b0d15afb0f4e2de13a729ed","tests/dummy_book/src/first/index.md":"e7d1af4cb454c0be73bf1e2f01a97541fba385cd04ac5c9a7acc99809adedee8","tests/dummy_book/src/first/nested.md":"3b20dd48744dbf0ff1f241f4cf114c749106e32fbe7678da2dacb7f0a796c84d","tests/dummy_book/src/first/recursive.md":"9b574239c94c24412dbd918d7b85f557a80cec44d245663cfe1ecdd8ed16765e","tests/dummy_book/src/intro.md":"2749920beee7f563f3ace2bbef204dc66382e052c7945bf27e66912351959a90","tests/dummy_book/src/second.md":"f01b5e2cdeb8319e88b3c70fcfccdd4f7269084b048dbf2a5d91c52bcaae4235","tests/dummy_book/src/second/nested.md":"0d85d8079b0750d0aef66365029dfb9b2ad96dd68b5402c7ad0201a3b006e638","tests/dummy_book/src2/README.md":"1bcffb061e737e022f132f78a2dd3193fc0951d0b104e50ddc860d9bc260f505","tests/dummy_book/src2/SUMMARY.md":"4354bec1cae7db3c48dfe869e28e8e29958daef937b33da5e729211372ccb9c9","tests/dummy_book/src2/first/README.md":"ba505ed6c1e18c85ce2ca7070021c719933ce2cf9f28de8565c188c0e4a95d87","tests/dummy_book/src2/second/README.md":"2fb4a90a1359fe3725c3d95888452afd514b0b86bdc4e2768442a71bf5b642a0","tests/dummy_book/src2/second/index.md":"5bf990bec982b9e87d8dfb230fb2dfc96318d9065f97a3d3c5cf27bd134c8bdd","tests/init.rs":"4d8c3ee3ab76e93e4ece264a272eee53f907d25dedfe545e9b9ef50221b346a8","tests/parse_existing_summary_files.rs":"48c56da96852c62784c76d6f2198042d3ec448701ba57534c4220ef466085783","tests/rendered_output.rs":"49e188a00026b2c88eb67f8b66d705b619993bb83f48832811ac31d56a736a30","tests/searchindex_fixture.json":"71571ae71e90d0b26ee5ce5fafea5dc42ed2e48a1eebda8cd0ede56b5dbe2abc","tests/summary_md_files/example_book.md":"e1dd09043d9548612b0bb4e607a8796317272aa1fe7a2bda55db6e6f47d3fc5a","tests/summary_md_files/rust_by_example.md":"c46c8eab64780297b851be196a04d573da69553f4d9c33e24fbd5fb2867efbfd","tests/summary_md_files/rust_ffi_guide.md":"26874d9ad22cfdc2a587e7a495a4404247821d2b6e8eabe07334cacc5a4ea365","tests/summary_md_files/the_book-2nd_edition.md":"7ae64929c45aa7d67560c77e5280a540c22d1b0d2f8fd85f8392ce064c2d5f0a","tests/testing.rs":"004209bacbd9e25a8d6bd420f9249dbe87d3576ba53e8dbf04ff98def3d6a821"},"package":"0ba0d44cb4089c741b9a91f3e5218298a40699c2f3a070a85014eed290c60819"} \ No newline at end of file +{"files":{"CHANGELOG.md":"4c0379600028c34fe9781b6e88d29f20d2393549230fc383b200bd6a463fcd6e","CONTRIBUTING.md":"0137d8c648b9500dda658f2bdde230f989f99897e644bc3006f3134df26d2146","Cargo.toml":"ba601bb4ef8be7947cf4de53e83bc3e15a6efa27f79f2a5f7fa9b8f6b650cfc7","LICENSE":"af175b9d96ee93c21a036152e1b905b0b95304d4ae8c2c921c7609100ba8df7e","README.md":"b32c45047ce4e150f947d6efe97756b3829e6a2df8c55854940949a671a485f4","appveyor.yml":"4ded0ab336adfac79acfbec82dcbb02857b49f5ba252a2d95fad77c7d8033c35","ci/before_deploy.sh":"4f01a05883c02ffb77380107f0f6a360edcf613dbb3e69a2790d99895d24e6d6","examples/nop-preprocessor.rs":"4507dd5a7794f09d973234d6561f36099b2c425961f7ac75afa4b409c776a7e7","release.toml":"25e91966f4a77515244adf5775d638590916c550f9d25bba6024d629b71840e8","src/book/book.rs":"441c00bcc96d1431a858a0cd70856bda83624603c81d07163a51a6de4858750f","src/book/init.rs":"dc98684393a7892ea94cf0213f02cbbcac7a87cad27846e4a028438859d22f3b","src/book/mod.rs":"fac96db5c721aaa337c48d12a5e5b3db04230bf990469ce7d89e93eaeab10c59","src/book/summary.rs":"3926207aff0b5574976a44cf288b16fe957fcb44610bc15691d4f7e1436ac781","src/cmd/build.rs":"7a87f609ad245a808137c9ff67a92b14238c8b01c3afc834ce166f3ff161a58f","src/cmd/clean.rs":"47a9a285a51e6ab515e35e316b712e647ad6c484219b8e65755e8fd884261317","src/cmd/init.rs":"3161219d9c4375d296c2f39fdb9cffdad09b373b46f1af5b9543173671a58e5b","src/cmd/mod.rs":"29116e5ca90e916a5f4ce62581a29508670ef184ec3e20569e2ad90b57472abe","src/cmd/serve.rs":"6527174c27f5fc12bf422d7b5031f0ee9e9ac74dc8aa9205aaf3344e022f04be","src/cmd/test.rs":"405e82cc63f212ec6f41e2017d34aba369c8d581b9c1431c8696d787aa2ee1cf","src/cmd/watch.rs":"3928fd9f34d45be0ae4c4e52012cfb92cc9571e62a8520e4ef55b3a7e1a12700","src/config.rs":"47ee98203e5ea33b28759ee09b47d65f44e868b3f1d85756480cd1b0f82f9719","src/lib.rs":"d705d12d4834e23cf1c4f1db883b5bb18cc2d640a8ff57a005eda3055ca79560","src/main.rs":"97122013281f59528d5d254e301f141f5111af5c5cbdadecbb8ebbac0e047bae","src/preprocess/cmd.rs":"1997b128f8f63c8d37a2f3f518640e9ca4df776497e008dffdd7f39efa7fa6f5","src/preprocess/index.rs":"c544f686489e96ad0516a84dd3541f018f164f0bb7a5f7ad245f12a6a94eed62","src/preprocess/links.rs":"9039f1815672cfc29d65d113639293b0da2f0d4f43646af0cc68621d2c2b71a7","src/preprocess/mod.rs":"b699f993473abdf6e4abbe038c8286b14312003e5d4713d946b9ae87047270e7","src/renderer/html_handlebars/hbs_renderer.rs":"4c497553974e7c7d688fe81ad83d7a0e40f02aadb1d7f5f1022ffd9b4dd67287","src/renderer/html_handlebars/helpers/mod.rs":"d83520feecce350b03b7ffaa9f34d6db2fe7316a46562be694b8eef537124191","src/renderer/html_handlebars/helpers/navigation.rs":"a3bc1417e713b85b195f5005ce66ff187ffe8bf4c456b2d9ff9fa11e1fe2fc35","src/renderer/html_handlebars/helpers/theme.rs":"dec923c3f80cae5a48774d62159a5ca47afb218372fb728ef1e0c8bf5ab6d3a6","src/renderer/html_handlebars/helpers/toc.rs":"e63ab060344e3128372a2616a5e7a76b4e1f2eef16432ad75299e41bf6776455","src/renderer/html_handlebars/mod.rs":"b6be4801cf49040edc9dad216ed12c26dce87e2dc4724ee24729e4a8b67734b0","src/renderer/html_handlebars/search.rs":"4af40fbc60fefe5a6cac91e94400c18ad5cd5394ecee511142c32072ef255bcc","src/renderer/mod.rs":"9d15a25ffa62ece952b5bf429bc6bf4548a9f33dca96d7e41b63deb0c76e17b5","src/theme/FontAwesome/css/font-awesome.min.css":"799aeb25cc0373fdee0e1b1db7ad6c2f6a0e058dfadaa3379689f583213190bd","src/theme/FontAwesome/fonts/FontAwesome.otf":"444dd4366615ffc4a16d012b2fa90137065d3ccb410fa6fd5e4ddd7b5e4ffcd5","src/theme/FontAwesome/fonts/fontawesome-webfont.eot":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","src/theme/FontAwesome/fonts/fontawesome-webfont.svg":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","src/theme/FontAwesome/fonts/fontawesome-webfont.ttf":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","src/theme/FontAwesome/fonts/fontawesome-webfont.woff":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","src/theme/FontAwesome/fonts/fontawesome-webfont.woff2":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","src/theme/ayu-highlight.css":"92a7374e1ef56769b647082c45918eb61f8fc5090d010c1afd28e9df05f4c49b","src/theme/book.js":"9ccffac63253558fa1ea84d28820f3bf0c57c4d45e5806d7a900f634c3272daa","src/theme/clipboard.min.js":"1626706afc88d95ebe1173b553ec732c6dc82a576989315fdf5e7779af738a44","src/theme/css/chrome.css":"dbbeb21cb925e10cef71fa45ea6951073cef839e1f8c5dcbd2ea2153c39fae26","src/theme/css/general.css":"c19f4b5384995f5de2ef27bd51545fc7db640a883d8ee2748e8574c036e5ff47","src/theme/css/print.css":"a4278dff9af38765eb9d344aa56dcc652ac79c73afc408385b62a4b611b89c14","src/theme/css/variables.css":"11f1ef43987922056ebcd63eb0bbea7a45dfdc5b10706b7011f585ecf6ba7c0f","src/theme/favicon.png":"8114d1fc74f4b5621ad9afde7746ed9cf7e420be317a6e29023d2298d58aa15b","src/theme/header.hbs":"1fd27c9ccd016060dc4d6e77f12bf58b26e7c604aebe2577a67097f95a3de70a","src/theme/highlight.css":"6ebb896cc720d92a56def939b787cb25a2facfcfa9d95eeac9f979b092f15716","src/theme/highlight.js":"57734fb7391993c864cd9303c9c80fc0b3ad3dea5daa5e57fd762303365c15e5","src/theme/index.hbs":"48ec8dd2c6840808ba673c212ecc65989cd7118e0a67e9bf6ea94114fe341c33","src/theme/mod.rs":"f94db6b0fcb4c94e7051eb6448a285c99b0d53a0e1f4bcce3a18b2db5e9044de","src/theme/playpen_editor/ace.js":"2a3cd908c9619862b52f621ce2a40f76b772eb51c17308b14bd26d1809af8f87","src/theme/playpen_editor/editor.js":"5d21235c3eb2fd14ec50f312fc4caeb0d8798c6a614c58c671dcac648faf1a08","src/theme/playpen_editor/mod.rs":"6a2a9a265e4a4354c59bad513f9f3e676b0b32123fb193847434071cfa28ea28","src/theme/playpen_editor/mode-rust.js":"2c9d5c9af5ae32612aef1ca5653e3473ed40747d36ecb4a97719ff14707d8535","src/theme/playpen_editor/theme-dawn.js":"4493f9c88ed7185f7bb4195be77018d21cdc439a34bd4e5da64b566eb996fbe8","src/theme/playpen_editor/theme-tomorrow_night.js":"9dbe62a913ebe3fd9667f41f69c0301bacd963081c69abb0219e4acac4710f60","src/theme/searcher/elasticlunr.min.js":"ef4e11c157b1e2e89782d30bd726f2d5ff7834ea5e26ad02474325f8b1f126c9","src/theme/searcher/mark.min.js":"09e88c2cfaf23ea8a37b5681433eafea97033af632ecc948c8c1ee9944647743","src/theme/searcher/mod.rs":"36979040719b2fa39d1b78808e41cdb6e52e0ea5137c84820b437ed015278072","src/theme/searcher/searcher.js":"cb2e829c9a1efb9063231e0139abd7a1070306b26e9a0e5da83376f742995f06","src/theme/tomorrow-night.css":"243cb61aa526cef79b3545b1c7f2b681747dd346867c8ceb36c69487acc390fb","src/utils/fs.rs":"feeaad728def0ba7cc40152c8837a1d8ad40c3ec072539273596eadea768fc05","src/utils/mod.rs":"c0b68777d10711ee7669e7988950ea42200ddd2f7eacf3fa70c392bcf0585002","src/utils/string.rs":"1d5446c88d5a33093a41f9255abf2a88d763e2d746119c9d18e8e2f0a98b001b","tests/alternative_backends.rs":"16ef2db46ee8f17c13a7f20f26420f6de738ba645a5b06189a23a143af8688b2","tests/build_process.rs":"a958404fc41ff5c00b08b4c69d26f0862160e20c781b4bea88977d85304b6ef5","tests/custom_preprocessors.rs":"22a5da0ed34ab2fe85d87ceb70e06c2a5065d66c363a39ce7d45715ae974ad1c","tests/dummy_book/mod.rs":"d18cf3b96d9769b1bceea5bb8e9a5447f8441b6556d2d371eb8b42fa68a57714","tests/dummy_book/src/README.md":"2f6e578b9f31ff5e1d18ae40865355d59e56a23e02798bd8166751245ef4eb9b","tests/dummy_book/src/SUMMARY.md":"09c7868f74a36197a0335eeda0abde6fb5abbda4410087376b6d6c59206d8407","tests/dummy_book/src/conclusion.md":"eca0543344979e938b43debf3d310290a628e8b7b45d3d9bec63c21e61284a4c","tests/dummy_book/src/example.rs":"3be109d6faa3c6104c8fb5e8ffdfe3eba73d0a5ed4f537685fe2cf2c36e657d0","tests/dummy_book/src/first/includes.md":"747f8f1eb4d394c1fdb773acddb7ffdc641e3ad71b0d15afb0f4e2de13a729ed","tests/dummy_book/src/first/index.md":"e7d1af4cb454c0be73bf1e2f01a97541fba385cd04ac5c9a7acc99809adedee8","tests/dummy_book/src/first/markdown.md":"461753f7f5105e35bc246c752065a44ea1d238f6890bd01b7c34d0a5746f7902","tests/dummy_book/src/first/nested-test.rs":"ca4cdf552842a957be49ffc753f7585dba3c0036a076fea68174719599d426fa","tests/dummy_book/src/first/nested.md":"87aca9b35095125e1d969b8ea79fbf77c34d01b798ba28158e5209d65e3c2525","tests/dummy_book/src/first/recursive.md":"9b574239c94c24412dbd918d7b85f557a80cec44d245663cfe1ecdd8ed16765e","tests/dummy_book/src/intro.md":"2749920beee7f563f3ace2bbef204dc66382e052c7945bf27e66912351959a90","tests/dummy_book/src/second.md":"f01b5e2cdeb8319e88b3c70fcfccdd4f7269084b048dbf2a5d91c52bcaae4235","tests/dummy_book/src/second/nested.md":"3fe443270d0570bc1075347ca910939f037c74167ec97fc34c377690150d1cc6","tests/dummy_book/src2/README.md":"1bcffb061e737e022f132f78a2dd3193fc0951d0b104e50ddc860d9bc260f505","tests/dummy_book/src2/SUMMARY.md":"4354bec1cae7db3c48dfe869e28e8e29958daef937b33da5e729211372ccb9c9","tests/dummy_book/src2/first/README.md":"ba505ed6c1e18c85ce2ca7070021c719933ce2cf9f28de8565c188c0e4a95d87","tests/dummy_book/src2/second/README.md":"2fb4a90a1359fe3725c3d95888452afd514b0b86bdc4e2768442a71bf5b642a0","tests/dummy_book/src2/second/index.md":"5bf990bec982b9e87d8dfb230fb2dfc96318d9065f97a3d3c5cf27bd134c8bdd","tests/init.rs":"1cf886e134047a491fe590f22885c0340a366268cc59b598f9707252a373b9b1","tests/parse_existing_summary_files.rs":"bc0c2914bfd58f7b1aae39debd9ab3367ba628b3298b0d1d0d614c5550d50f11","tests/rendered_output.rs":"6fe64fcc6f4848e2ef0ef74c8281d3cab780d03a3f05cda3f96e75f4bd2c378b","tests/searchindex_fixture.json":"624048338cc167fdfb3658926758334712689cdddb7b195e6f8e235b35cc6751","tests/summary_md_files/example_book.md":"e1dd09043d9548612b0bb4e607a8796317272aa1fe7a2bda55db6e6f47d3fc5a","tests/summary_md_files/rust_by_example.md":"c46c8eab64780297b851be196a04d573da69553f4d9c33e24fbd5fb2867efbfd","tests/summary_md_files/rust_ffi_guide.md":"26874d9ad22cfdc2a587e7a495a4404247821d2b6e8eabe07334cacc5a4ea365","tests/summary_md_files/the_book-2nd_edition.md":"7ae64929c45aa7d67560c77e5280a540c22d1b0d2f8fd85f8392ce064c2d5f0a","tests/testing.rs":"14d2d7b202a2555c877f83e8f5ec683fb9319ab66bdea1bb54ab76eebf332a22"},"package":"0c8e2c6442721202fb3b5800741aaafcc7076cdd199b326f0a39ce52a042cd37"} \ No newline at end of file diff --git a/vendor/mdbook/CHANGELOG.md b/vendor/mdbook/CHANGELOG.md new file mode 100644 index 0000000000..fd18a4ac5b --- /dev/null +++ b/vendor/mdbook/CHANGELOG.md @@ -0,0 +1,190 @@ +# Changelog + +## mdBook 0.3.0 +[6cbc41d...84d4063](https://github.com/rust-lang-nursery/mdBook/compare/6cbc41d...84d4063) + +### Added +- Added ability to resize the sidebar. + [#849](https://github.com/rust-lang-nursery/mdBook/pull/849) +- Added `load_with_config_and_summary` function to `MDBook` to be able to + build a book with a custom `Summary`. + [#883](https://github.com/rust-lang-nursery/mdBook/pull/883) +- Set `noindex` on `print.html` page to prevent robots from indexing it. + [#844](https://github.com/rust-lang-nursery/mdBook/pull/844) +- Added support for ~~strikethrough~~ and GitHub-style tasklists. + [#952](https://github.com/rust-lang-nursery/mdBook/pull/952) + +### Changed +- Command-line help output is now colored. + [#861](https://github.com/rust-lang-nursery/mdBook/pull/861) +- The build directory is now deleted before rendering starts, instead of after + if finishes. + [#878](https://github.com/rust-lang-nursery/mdBook/pull/878) +- Removed dependency on `same-file` crate. + [#903](https://github.com/rust-lang-nursery/mdBook/pull/903) +- 💥 Renamed `with_preprecessor` to `with_preprocessor`. + [#906](https://github.com/rust-lang-nursery/mdBook/pull/906) +- Updated ACE editor to 1.4.4, should remove a JavaScript console warning. + [#935](https://github.com/rust-lang-nursery/mdBook/pull/935) +- Dependencies have been updated. + [#934](https://github.com/rust-lang-nursery/mdBook/pull/934) + [#945](https://github.com/rust-lang-nursery/mdBook/pull/945) +- Highlight.js has been updated. This fixes some TOML highlighting, and adds + Julia support. + [#942](https://github.com/rust-lang-nursery/mdBook/pull/942) +- 🔥 Updated to pulldown-cmark 0.5. This may have significant changes to the + formatting of existing books, as the newer version has more accurate + interpretation of the CommonMark spec and a large number of bug fixes and + changes. + [#898](https://github.com/rust-lang-nursery/mdBook/pull/898) +- The `diff` language should now highlight correctly. + [#943](https://github.com/rust-lang-nursery/mdBook/pull/943) +- Make the blank region of a header not clickable. + [#948](https://github.com/rust-lang-nursery/mdBook/pull/948) +- Rustdoc tests now use the preprocessed content instead of the raw, + unpreprocessed content. + [#891](https://github.com/rust-lang-nursery/mdBook/pull/891) + +### Fixed +- Fixed file change detection so that `mdbook serve` only reloads once when + multiple files are changed at once. + [#870](https://github.com/rust-lang-nursery/mdBook/pull/870) +- Fixed on-hover color highlighting for links in sidebar. + [#834](https://github.com/rust-lang-nursery/mdBook/pull/834) +- Fixed loss of focus when clicking the "Copy" button in code blocks. + [#867](https://github.com/rust-lang-nursery/mdBook/pull/867) +- Fixed incorrectly stripping the path for `additional-js` files. + [#796](https://github.com/rust-lang-nursery/mdBook/pull/796) +- Fixed color of `code spans` that are links. + [#905](https://github.com/rust-lang-nursery/mdBook/pull/905) +- Fixed "next" navigation on index.html. + [#916](https://github.com/rust-lang-nursery/mdBook/pull/916) +- Fixed keyboard chapter navigation for `file` urls. + [#915](https://github.com/rust-lang-nursery/mdBook/pull/915) +- Fixed bad wrapping for inline code on some browsers. + [#818](https://github.com/rust-lang-nursery/mdBook/pull/818) +- Properly load an existing `SUMMARY.md` in `mdbook init`. + [#841](https://github.com/rust-lang-nursery/mdBook/pull/841) +- Fixed some broken links in `print.html`. + [#871](https://github.com/rust-lang-nursery/mdBook/pull/871) +- The Rust Playground link now supports the 2018 edition. + [#946](https://github.com/rust-lang-nursery/mdBook/pull/946) + +## mdBook 0.2.3 (2018-01-18) +[2c20c99...6cbc41d](https://github.com/rust-lang-nursery/mdBook/compare/2c20c99...6cbc41d) + +### Added +- Added an optional button to the top of the page which will link to a git + repository. Use the `git-repository-url` and `git-repository-icon` options + in the `[output.html]` section to enable it and set its appearance. + [#802](https://github.com/rust-lang-nursery/mdBook/pull/802) +- Added a `default-theme` option to the `[output.html]` section. + [#804](https://github.com/rust-lang-nursery/mdBook/pull/804) + +### Changed +- 💥 Header ID anchors no longer add an arbitrary `a` character for headers + that start with a non-ascii-alphabetic character. + [#788](https://github.com/rust-lang-nursery/mdBook/pull/788) + +### Fixed +- Fix websocket hostname usage + [#865](https://github.com/rust-lang-nursery/mdBook/pull/865) +- Fixing links in print.html + [#866](https://github.com/rust-lang-nursery/mdBook/pull/866) + +## mdBook 0.2.2 (2018-10-19) +[7e2e095...2c20c99](https://github.com/rust-lang-nursery/mdBook/compare/7e2e095...2c20c99) + +### Added +- 🎉 Process-based custom preprocessors. See [the + docs](https://rust-lang-nursery.github.io/mdBook/for_developers/preprocessors.html) + for more. + [#792](https://github.com/rust-lang-nursery/mdBook/pull/792) + +- 🎉 Configurable preprocessors. + + Added `build.use-default-preprocessors` boolean TOML key to allow disabling + the built-in `links` and `index` preprocessors. + + Added `[preprocessor]` TOML tables to configure each preprocessor. + + Specifying `[preprocessor.links]` or `[preprocessor.index]` will enable the + respective built-in preprocessor if `build.use-default-preprocessors` is + `false`. + + Added `fn supports_renderer(&self, renderer: &str) -> bool` to the + `Preprocessor` trait to specify if the preprocessor supports the given + renderer. The default implementation always returns `true`. + + `Preprocessor::run` now takes a book by value instead of a mutable + reference. It should return a `Book` value with the intended modifications. + + Added `PreprocessorContext::renderer` to indicate the renderer being used. + + [#658](https://github.com/rust-lang-nursery/mdBook/pull/658) + [#787](https://github.com/rust-lang-nursery/mdBook/pull/787) + +### Fixed +- Fix paths to additional CSS and JavaScript files + [#777](https://github.com/rust-lang-nursery/mdBook/pull/777) +- Ensure section numbers are correctly incremented after a horizontal + separator + [#790](https://github.com/rust-lang-nursery/mdBook/pull/790) + +## mdBook 0.2.1 (2018-08-22) +[91ffca1...7e2e095](https://github.com/rust-lang-nursery/mdBook/compare/91ffca1...7e2e095) + +### Changed +- Update to handlebars-rs 1.0 + [#761](https://github.com/rust-lang-nursery/mdBook/pull/761) + +### Fixed +- Fix table colors, broken by Stylus -> CSS transition + [#765](https://github.com/rust-lang-nursery/mdBook/pull/765) + +## mdBook 0.2.0 (2018-08-02) + +### Changed +- 💥 This release changes how links are handled in mdBook. Previously, relative + links were interpreted relative to the book's root. In `0.2.0`+ links are + relative to the page they are in, and use the `.md` extension. This has [several + advantages](https://github.com/rust-lang-nursery/mdBook/pull/603#issue-166701447), + such as making links work in other markdown viewers like GitHub. You will + likely have to change links in your book to accommodate this change. For + example, a book with this layout: + + ``` + chapter_1/ + section_1.md + section_2.md + SUMMARY.md + ``` + + Previously a link in `section_1.md` to `section_2.md` would look like this: + ```markdown + [section_2](chapter_1/section_2.html) + ``` + + Now it must be changed to this: + ```markdown + [section_2](section_2.md) + ``` + +- 💥 `mdbook test --library-path` now accepts a comma-delimited list of + arguments rather than taking all following arguments. This makes it easier + to handle the trailing book directory argument without always needing to put + ` -- ` before it. Multiple instances of the option continue to be accepted: + `mdbook test -L foo -L bar`. + +- 💥 `mdbook serve` has some of its options renamed for clarity. See `mdbook + help serve` for details. + +- Embedded rust playpens now use the "stable" playground API. + [#754](https://github.com/rust-lang-nursery/mdBook/pull/754) + +### Fixed +- Escaped includes (`\{{#include file.rs}}`) will now render correctly. + [f30ce01](https://github.com/rust-lang-nursery/mdBook/commit/f30ce0184d71e342141145472bf816419d30a2c5) +- `index.html` will now render correctly when the book's first section is + inside a subdirectory. + [#756](https://github.com/rust-lang-nursery/mdBook/pull/756) diff --git a/vendor/mdbook/Cargo.toml b/vendor/mdbook/Cargo.toml index 38d97c6236..8409b2eac1 100644 --- a/vendor/mdbook/Cargo.toml +++ b/vendor/mdbook/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,11 +11,12 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "mdbook" -version = "0.2.3" +version = "0.3.0" authors = ["Mathieu David <mathieudavid@mathieudavid.org>", "Michael-F-Bryan <michaelfbryan@gmail.com>", "Matt Ickstadt <mattico8@gmail.com>"] -exclude = ["book-example/*"] -description = "Create books from markdown files" +exclude = ["/book-example/*"] +description = "Creates a book from markdown files" documentation = "http://rust-lang-nursery.github.io/mdBook/index.html" readme = "README.md" keywords = ["book", "gitbook", "rustbook", "markdown"] @@ -26,7 +27,7 @@ repository = "https://github.com/rust-lang-nursery/mdBook" name = "mdbook" doc = false [dependencies.ammonia] -version = "1.1" +version = "2.1" optional = true [dependencies.chrono] @@ -41,20 +42,22 @@ optional = true default-features = false [dependencies.env_logger] -version = "0.5" +version = "0.6" [dependencies.error-chain] version = "0.12" [dependencies.handlebars] version = "1.0" +features = ["no_dir_source"] +default-features = false [dependencies.iron] version = "0.6" optional = true [dependencies.itertools] -version = "0.7" +version = "0.8" [dependencies.lazy_static] version = "1.0" @@ -73,7 +76,7 @@ optional = true version = "1.1" [dependencies.pulldown-cmark] -version = "0.1.2" +version = "0.5" [dependencies.regex] version = "1.0.0" @@ -98,19 +101,16 @@ optional = true version = "3.0" [dependencies.toml] -version = "0.4.8" +version = "0.5.1" [dependencies.toml-query] -version = "0.7" +version = "0.9" [dependencies.ws] -version = "0.7" +version = "0.8" optional = true [dev-dependencies.pretty_assertions] -version = "0.5" - -[dev-dependencies.pulldown-cmark-to-cmark] -version = "1.1.0" +version = "0.6" [dev-dependencies.select] version = "0.4" diff --git a/vendor/mdbook/README.md b/vendor/mdbook/README.md index 0af7e5b64a..dfe56a2db8 100644 --- a/vendor/mdbook/README.md +++ b/vendor/mdbook/README.md @@ -4,7 +4,7 @@ <tr> <td><strong>Linux / OS X</strong></td> <td> - <a href="https://travis-ci.org/rust-lang-nursery/mdBook"><img src="https://travis-ci.org/rust-lang-nursery/mdBook.svg?branch=master"></a> + <a href="https://travis-ci.com/rust-lang-nursery/mdBook"><img src="https://travis-ci.com/rust-lang-nursery/mdBook.svg?branch=master"></a> </td> </tr> <tr> @@ -57,7 +57,7 @@ There are multiple ways to install mdBook. another CI server, we recommend that you specify a semver version range for mdBook when you install it through your script! - This will constrain the server to install the latests **non-breaking** + This will constrain the server to install the latest **non-breaking** version of mdBook and will prevent your books from failing to build because we released a new version. For example: @@ -65,7 +65,7 @@ There are multiple ways to install mdBook. cargo install mdbook --vers "^0.1.0" ``` -3. **From Git** +3. **From Git** The version published to crates.io will ever so slightly be behind the version hosted here on GitHub. If you need the latest version you can build @@ -77,7 +77,7 @@ There are multiple ways to install mdBook. Again, make sure to add the Cargo bin directory to your `PATH`. -4. **For Contributions** +4. **For Contributions** If you want to contribute to mdBook you will have to clone the repository on your local machine: @@ -152,9 +152,9 @@ party plugins. These plugins are just programs which will be invoked during the build process and are split into roughly two categories, *preprocessors* and *renderers*. -Preprocessors are used to transform a book before it is sent to a renderer. -One example would be to replace all occurrences of -`{{#include some_file.ext}}` with the contents of that file. Some existing +Preprocessors are used to transform a book before it is sent to a renderer. +One example would be to replace all occurrences of +`{{#include some_file.ext}}` with the contents of that file. Some existing preprocessors are: - `index` - a built-in preprocessor (enabled by default) which will transform diff --git a/vendor/mdbook/appveyor.yml b/vendor/mdbook/appveyor.yml index d012f44f58..78dff572dd 100644 --- a/vendor/mdbook/appveyor.yml +++ b/vendor/mdbook/appveyor.yml @@ -7,14 +7,7 @@ environment: RUST_CHANNEL: stable - TARGET: x86_64-pc-windows-msvc RUST_CHANNEL: stable - # Beta channel - - TARGET: i686-pc-windows-msvc - RUST_CHANNEL: beta - - TARGET: x86_64-pc-windows-msvc - RUST_CHANNEL: beta # Nightly channel - - TARGET: i686-pc-windows-msvc - RUST_CHANNEL: nightly - TARGET: x86_64-pc-windows-msvc RUST_CHANNEL: nightly @@ -51,8 +44,7 @@ before_deploy: deploy: description: 'Windows release' artifact: /.*\.zip/ - auth_token: - secure: QQhjKVyz7mpjlyGhlXytbFQQfKFQWTahHkD+B0NzIUoEVqO7ZLWjnoWasvLqW4nE + auth_token: $(GITHUB_TOKEN) provider: GitHub on: RUST_CHANNEL: stable diff --git a/vendor/mdbook/examples/de-emphasize.rs b/vendor/mdbook/examples/de-emphasize.rs deleted file mode 100644 index 1cdf082307..0000000000 --- a/vendor/mdbook/examples/de-emphasize.rs +++ /dev/null @@ -1,80 +0,0 @@ -//! An example preprocessor for removing all forms of emphasis from a markdown -//! book. - -extern crate mdbook; -extern crate pulldown_cmark; -extern crate pulldown_cmark_to_cmark; - -use mdbook::book::{Book, BookItem, Chapter}; -use mdbook::errors::{Error, Result}; -use mdbook::preprocess::{Preprocessor, PreprocessorContext}; -use pulldown_cmark::{Event, Parser, Tag}; -use pulldown_cmark_to_cmark::fmt::cmark; - -const NAME: &str = "md-links-to-html-links"; - -fn main() { - panic!("This example is intended to be part of a library"); -} - -#[allow(dead_code)] -struct Deemphasize; - -impl Preprocessor for Deemphasize { - fn name(&self) -> &str { - NAME - } - - fn run(&self, _ctx: &PreprocessorContext, mut book: Book) -> Result<Book> { - eprintln!("Running '{}' preprocessor", self.name()); - let mut num_removed_items = 0; - - process(&mut book.sections, &mut num_removed_items)?; - - eprintln!( - "{}: removed {} events from markdown stream.", - self.name(), - num_removed_items - ); - - Ok(book) - } -} - -fn process<'a, I>(items: I, num_removed_items: &mut usize) -> Result<()> -where - I: IntoIterator<Item = &'a mut BookItem> + 'a, -{ - for item in items { - if let BookItem::Chapter(ref mut chapter) = *item { - eprintln!("{}: processing chapter '{}'", NAME, chapter.name); - - let md = remove_emphasis(num_removed_items, chapter)?; - chapter.content = md; - } - } - - Ok(()) -} - -fn remove_emphasis(num_removed_items: &mut usize, chapter: &mut Chapter) -> Result<String> { - let mut buf = String::with_capacity(chapter.content.len()); - - let events = Parser::new(&chapter.content).filter(|e| { - let should_keep = match *e { - Event::Start(Tag::Emphasis) - | Event::Start(Tag::Strong) - | Event::End(Tag::Emphasis) - | Event::End(Tag::Strong) => false, - _ => true, - }; - if !should_keep { - *num_removed_items += 1; - } - should_keep - }); - - cmark(events, &mut buf, None) - .map(|_| buf) - .map_err(|err| Error::from(format!("Markdown serialization failed: {}", err))) -} diff --git a/vendor/mdbook/examples/nop-preprocessor.rs b/vendor/mdbook/examples/nop-preprocessor.rs index 374ee60f5d..f176694410 100644 --- a/vendor/mdbook/examples/nop-preprocessor.rs +++ b/vendor/mdbook/examples/nop-preprocessor.rs @@ -1,12 +1,8 @@ -extern crate clap; -extern crate mdbook; -extern crate serde_json; - +use crate::nop_lib::Nop; use clap::{App, Arg, ArgMatches, SubCommand}; use mdbook::book::Book; use mdbook::errors::Error; use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext}; -use nop_lib::Nop; use std::io; use std::process; @@ -28,11 +24,9 @@ fn main() { if let Some(sub_args) = matches.subcommand_matches("supports") { handle_supports(&preprocessor, sub_args); - } else { - if let Err(e) = handle_preprocessing(&preprocessor) { - eprintln!("{}", e); - process::exit(1); - } + } else if let Err(e) = handle_preprocessing(&preprocessor) { + eprintln!("{}", e); + process::exit(1); } } diff --git a/vendor/mdbook/src/book/book.rs b/vendor/mdbook/src/book/book.rs index b69e98ab86..6a31c9e8c6 100644 --- a/vendor/mdbook/src/book/book.rs +++ b/vendor/mdbook/src/book/book.rs @@ -5,8 +5,8 @@ use std::io::{Read, Write}; use std::path::{Path, PathBuf}; use super::summary::{parse_summary, Link, SectionNumber, Summary, SummaryItem}; -use config::BuildConfig; -use errors::*; +use crate::config::BuildConfig; +use crate::errors::*; /// Load a book into memory from its `src/` directory. pub fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book> { @@ -82,7 +82,7 @@ impl Book { } /// Get a depth-first iterator over the items in the book. - pub fn iter(&self) -> BookItems { + pub fn iter(&self) -> BookItems<'_> { BookItems { items: self.sections.iter().collect(), } @@ -116,7 +116,7 @@ where I: IntoIterator<Item = &'a mut BookItem>, { for item in items { - if let &mut BookItem::Chapter(ref mut ch) = item { + if let BookItem::Chapter(ch) = item { for_each_mut(func, &mut ch.sub_items); } @@ -179,7 +179,7 @@ impl Chapter { /// /// You need to pass in the book's source directory because all the links in /// `SUMMARY.md` give the chapter locations relative to it. -fn load_book_from_disk<P: AsRef<Path>>(summary: &Summary, src_dir: P) -> Result<Book> { +pub(crate) fn load_book_from_disk<P: AsRef<Path>>(summary: &Summary, src_dir: P) -> Result<Book> { debug!("Loading the book from disk"); let src_dir = src_dir.as_ref(); @@ -286,7 +286,7 @@ impl<'a> Iterator for BookItems<'a> { } impl Display for Chapter { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if let Some(ref section_number) = self.number { write!(f, "{} ", section_number)?; } @@ -301,7 +301,7 @@ mod tests { use std::io::Write; use tempfile::{Builder as TempFileBuilder, TempDir}; - const DUMMY_SRC: &'static str = " + const DUMMY_SRC: &str = " # Dummy Chapter this is some dummy text. @@ -317,7 +317,7 @@ And here is some \ let chapter_path = temp.path().join("chapter_1.md"); File::create(&chapter_path) .unwrap() - .write(DUMMY_SRC.as_bytes()) + .write_all(DUMMY_SRC.as_bytes()) .unwrap(); let link = Link::new("Chapter 1", chapter_path); @@ -333,7 +333,7 @@ And here is some \ File::create(&second_path) .unwrap() - .write_all("Hello World!".as_bytes()) + .write_all(b"Hello World!") .unwrap(); let mut second = Link::new("Nested Chapter 1", &second_path); @@ -481,7 +481,8 @@ And here is some \ .filter_map(|i| match *i { BookItem::Chapter(ref ch) => Some(ch.name.clone()), _ => None, - }).collect(); + }) + .collect(); let should_be: Vec<_> = vec![ String::from("Chapter 1"), String::from("Hello World"), diff --git a/vendor/mdbook/src/book/init.rs b/vendor/mdbook/src/book/init.rs index 4acf4b5256..f940e1faf7 100644 --- a/vendor/mdbook/src/book/init.rs +++ b/vendor/mdbook/src/book/init.rs @@ -1,12 +1,11 @@ use std::fs::{self, File}; use std::io::Write; use std::path::PathBuf; -use toml; use super::MDBook; -use config::Config; -use errors::*; -use theme; +use crate::config::Config; +use crate::errors::*; +use crate::theme; /// A helper for setting up a new book and its directory structure. #[derive(Debug, Clone, PartialEq)] @@ -173,15 +172,19 @@ impl BookBuilder { let src_dir = self.root.join(&self.config.book.src); let summary = src_dir.join("SUMMARY.md"); - let mut f = File::create(&summary).chain_err(|| "Unable to create SUMMARY.md")?; - writeln!(f, "# Summary")?; - writeln!(f)?; - writeln!(f, "- [Chapter 1](./chapter_1.md)")?; - - let chapter_1 = src_dir.join("chapter_1.md"); - let mut f = File::create(&chapter_1).chain_err(|| "Unable to create chapter_1.md")?; - writeln!(f, "# Chapter 1")?; - + if !summary.exists() { + trace!("No summary found creating stub summary and chapter_1.md."); + let mut f = File::create(&summary).chain_err(|| "Unable to create SUMMARY.md")?; + writeln!(f, "# Summary")?; + writeln!(f)?; + writeln!(f, "- [Chapter 1](./chapter_1.md)")?; + + let chapter_1 = src_dir.join("chapter_1.md"); + let mut f = File::create(&chapter_1).chain_err(|| "Unable to create chapter_1.md")?; + writeln!(f, "# Chapter 1")?; + } else { + trace!("Existing summary found, no need to create stub files."); + } Ok(()) } diff --git a/vendor/mdbook/src/book/mod.rs b/vendor/mdbook/src/book/mod.rs index 48537a37f9..db5d11f3d3 100644 --- a/vendor/mdbook/src/book/mod.rs +++ b/vendor/mdbook/src/book/mod.rs @@ -16,17 +16,18 @@ pub use self::summary::{parse_summary, Link, SectionNumber, Summary, SummaryItem use std::io::Write; use std::path::PathBuf; use std::process::Command; +use std::string::ToString; use tempfile::Builder as TempFileBuilder; use toml::Value; -use errors::*; -use preprocess::{ +use crate::errors::*; +use crate::preprocess::{ CmdPreprocessor, IndexPreprocessor, LinkPreprocessor, Preprocessor, PreprocessorContext, }; -use renderer::{CmdRenderer, HtmlHandlebars, RenderContext, Renderer}; -use utils; +use crate::renderer::{CmdRenderer, HtmlHandlebars, RenderContext, Renderer}; +use crate::utils; -use config::Config; +use crate::config::Config; /// The object used to manage and build a book. pub struct MDBook { @@ -36,10 +37,10 @@ pub struct MDBook { pub config: Config, /// A representation of the book's contents in memory. pub book: Book, - renderers: Vec<Box<Renderer>>, + renderers: Vec<Box<dyn Renderer>>, /// List of pre-processors to be run on the book - preprocessors: Vec<Box<Preprocessor>>, + preprocessors: Vec<Box<dyn Preprocessor>>, } impl MDBook { @@ -67,7 +68,7 @@ impl MDBook { config.update_from_env(); - if log_enabled!(::log::Level::Trace) { + if log_enabled!(log::Level::Trace) { for line in format!("Config: {:#?}", config).lines() { trace!("{}", line); } @@ -95,12 +96,34 @@ impl MDBook { }) } + /// Load a book from its root directory using a custom config and a custom summary. + pub fn load_with_config_and_summary<P: Into<PathBuf>>( + book_root: P, + config: Config, + summary: Summary, + ) -> Result<MDBook> { + let root = book_root.into(); + + let src_dir = root.join(&config.book.src); + let book = book::load_book_from_disk(&summary, &src_dir)?; + + let renderers = determine_renderers(&config); + let preprocessors = determine_preprocessors(&config)?; + + Ok(MDBook { + root, + config, + book, + renderers, + preprocessors, + }) + } + /// Returns a flat depth-first iterator over the elements of the book, /// it returns an [BookItem enum](bookitem.html): /// `(section: String, bookitem: &BookItem)` /// /// ```no_run - /// # extern crate mdbook; /// # use mdbook::MDBook; /// # use mdbook::book::BookItem; /// # #[allow(unused_variables)] @@ -122,7 +145,7 @@ impl MDBook { /// // etc. /// # } /// ``` - pub fn iter(&self) -> BookItems { + pub fn iter(&self) -> BookItems<'_> { self.book.iter() } @@ -159,7 +182,7 @@ impl MDBook { } /// Run the entire build process for a particular `Renderer`. - fn execute_build_process(&self, renderer: &Renderer) -> Result<()> { + fn execute_build_process(&self, renderer: &dyn Renderer) -> Result<()> { let mut preprocessed_book = self.book.clone(); let preprocess_ctx = PreprocessorContext::new( self.root.clone(), @@ -167,6 +190,19 @@ impl MDBook { renderer.name().to_string(), ); + let name = renderer.name(); + let build_dir = self.build_dir_for(name); + if build_dir.exists() { + debug!( + "Cleaning build dir for the \"{}\" renderer ({})", + name, + build_dir.display() + ); + + utils::fs::remove_dir_content(&build_dir) + .chain_err(|| "Unable to clear output directory")?; + } + for preprocessor in &self.preprocessors { if preprocessor_should_run(&**preprocessor, renderer, &self.config) { debug!("Running the {} preprocessor.", preprocessor.name()); @@ -180,19 +216,9 @@ impl MDBook { Ok(()) } - fn render(&self, preprocessed_book: &Book, renderer: &Renderer) -> Result<()> { + fn render(&self, preprocessed_book: &Book, renderer: &dyn Renderer) -> Result<()> { let name = renderer.name(); let build_dir = self.build_dir_for(name); - if build_dir.exists() { - debug!( - "Cleaning build dir for the \"{}\" renderer ({})", - name, - build_dir.display() - ); - - utils::fs::remove_dir_content(&build_dir) - .chain_err(|| "Unable to clear output directory")?; - } let render_context = RenderContext::new( self.root.clone(), @@ -215,7 +241,7 @@ impl MDBook { } /// Register a [`Preprocessor`](../preprocess/trait.Preprocessor.html) to be used when rendering the book. - pub fn with_preprecessor<P: Preprocessor + 'static>(&mut self, preprocessor: P) -> &mut Self { + pub fn with_preprocessor<P: Preprocessor + 'static>(&mut self, preprocessor: P) -> &mut Self { self.preprocessors.push(Box::new(preprocessor)); self } @@ -242,13 +268,12 @@ impl MDBook { if let BookItem::Chapter(ref ch) = *item { if !ch.path.as_os_str().is_empty() { let path = self.source_dir().join(&ch.path); - let content = utils::fs::file_to_string(&path)?; info!("Testing file: {:?}", path); // write preprocessed file to tempdir let path = temp_dir.path().join(&ch.path); let mut tmpf = utils::fs::create_file(&path)?; - tmpf.write_all(content.as_bytes())?; + tmpf.write_all(ch.content.as_bytes())?; let output = Command::new("rustdoc") .arg(&path) @@ -317,10 +342,10 @@ impl MDBook { } /// Look at the `Config` and try to figure out what renderers to use. -fn determine_renderers(config: &Config) -> Vec<Box<Renderer>> { - let mut renderers: Vec<Box<Renderer>> = Vec::new(); +fn determine_renderers(config: &Config) -> Vec<Box<dyn Renderer>> { + let mut renderers: Vec<Box<dyn Renderer>> = Vec::new(); - if let Some(output_table) = config.get("output").and_then(|o| o.as_table()) { + if let Some(output_table) = config.get("output").and_then(Value::as_table) { for (key, table) in output_table.iter() { // the "html" backend has its own Renderer if key == "html" { @@ -340,27 +365,27 @@ fn determine_renderers(config: &Config) -> Vec<Box<Renderer>> { renderers } -fn default_preprocessors() -> Vec<Box<Preprocessor>> { +fn default_preprocessors() -> Vec<Box<dyn Preprocessor>> { vec![ Box::new(LinkPreprocessor::new()), Box::new(IndexPreprocessor::new()), ] } -fn is_default_preprocessor(pre: &Preprocessor) -> bool { +fn is_default_preprocessor(pre: &dyn Preprocessor) -> bool { let name = pre.name(); name == LinkPreprocessor::NAME || name == IndexPreprocessor::NAME } /// Look at the `MDBook` and try to figure out what preprocessors to run. -fn determine_preprocessors(config: &Config) -> Result<Vec<Box<Preprocessor>>> { +fn determine_preprocessors(config: &Config) -> Result<Vec<Box<dyn Preprocessor>>> { let mut preprocessors = Vec::new(); if config.build.use_default_preprocessors { preprocessors.extend(default_preprocessors()); } - if let Some(preprocessor_table) = config.get("preprocessor").and_then(|v| v.as_table()) { + if let Some(preprocessor_table) = config.get("preprocessor").and_then(Value::as_table) { for key in preprocessor_table.keys() { match key.as_ref() { "links" => preprocessors.push(Box::new(LinkPreprocessor::new())), @@ -379,8 +404,8 @@ fn determine_preprocessors(config: &Config) -> Result<Vec<Box<Preprocessor>>> { fn interpret_custom_preprocessor(key: &str, table: &Value) -> Box<CmdPreprocessor> { let command = table .get("command") - .and_then(|c| c.as_str()) - .map(|s| s.to_string()) + .and_then(Value::as_str) + .map(ToString::to_string) .unwrap_or_else(|| format!("mdbook-{}", key)); Box::new(CmdPreprocessor::new(key.to_string(), command.to_string())) @@ -391,8 +416,8 @@ fn interpret_custom_renderer(key: &str, table: &Value) -> Box<CmdRenderer> { // prepended by "mdbook-" let table_dot_command = table .get("command") - .and_then(|c| c.as_str()) - .map(|s| s.to_string()); + .and_then(Value::as_str) + .map(ToString::to_string); let command = table_dot_command.unwrap_or_else(|| format!("mdbook-{}", key)); @@ -405,7 +430,11 @@ fn interpret_custom_renderer(key: &str, table: &Value) -> Box<CmdRenderer> { /// /// The `build.use-default-preprocessors` config option can be used to ensure /// default preprocessors always run if they support the renderer. -fn preprocessor_should_run(preprocessor: &Preprocessor, renderer: &Renderer, cfg: &Config) -> bool { +fn preprocessor_should_run( + preprocessor: &dyn Preprocessor, + renderer: &dyn Renderer, + cfg: &Config, +) -> bool { // default preprocessors should be run by default (if supported) if cfg.build.use_default_preprocessors && is_default_preprocessor(preprocessor) { return preprocessor.supports_renderer(renderer.name()); @@ -417,7 +446,7 @@ fn preprocessor_should_run(preprocessor: &Preprocessor, renderer: &Renderer, cfg if let Some(Value::Array(ref explicit_renderers)) = cfg.get(&key) { return explicit_renderers .iter() - .filter_map(|val| val.as_str()) + .filter_map(Value::as_str) .any(|name| name == renderer_name); } @@ -427,6 +456,7 @@ fn preprocessor_should_run(preprocessor: &Preprocessor, renderer: &Renderer, cfg #[cfg(test)] mod tests { use super::*; + use std::str::FromStr; use toml::value::{Table, Value}; #[test] @@ -494,7 +524,7 @@ mod tests { #[test] fn can_determine_third_party_preprocessors() { - let cfg_str: &'static str = r#" + let cfg_str = r#" [book] title = "Some Book" @@ -533,7 +563,7 @@ mod tests { #[test] fn config_respects_preprocessor_selection() { - let cfg_str: &'static str = r#" + let cfg_str = r#" [preprocessor.links] renderers = ["html"] "#; @@ -544,9 +574,9 @@ mod tests { let html = cfg .get_preprocessor("links") .and_then(|links| links.get("renderers")) - .and_then(|renderers| renderers.as_array()) + .and_then(Value::as_array) .and_then(|renderers| renderers.get(0)) - .and_then(|renderer| renderer.as_str()) + .and_then(Value::as_str) .unwrap(); assert_eq!(html, "html"); let html_renderer = HtmlHandlebars::default(); diff --git a/vendor/mdbook/src/book/summary.rs b/vendor/mdbook/src/book/summary.rs index 31bf0b9b84..817179c9c6 100644 --- a/vendor/mdbook/src/book/summary.rs +++ b/vendor/mdbook/src/book/summary.rs @@ -1,4 +1,4 @@ -use errors::*; +use crate::errors::*; use memchr::{self, Memchr}; use pulldown_cmark::{self, Event, Tag}; use std::fmt::{self, Display, Formatter}; @@ -195,7 +195,7 @@ macro_rules! collect_events { } impl<'a> SummaryParser<'a> { - fn new(text: &str) -> SummaryParser { + fn new(text: &str) -> SummaryParser<'_> { let pulldown_parser = pulldown_cmark::Parser::new(text); SummaryParser { @@ -259,7 +259,7 @@ impl<'a> SummaryParser<'a> { bail!(self.parse_error("Suffix chapters cannot be followed by a list")); } } - Some(Event::Start(Tag::Link(href, _))) => { + Some(Event::Start(Tag::Link(_type, href, _title))) => { let link = self.parse_link(href.to_string())?; items.push(SummaryItem::Link(link)); } @@ -397,7 +397,7 @@ impl<'a> SummaryParser<'a> { loop { match self.next_event() { Some(Event::Start(Tag::Paragraph)) => continue, - Some(Event::Start(Tag::Link(href, _))) => { + Some(Event::Start(Tag::Link(_type, href, _title))) => { let mut link = self.parse_link(href.to_string())?; let mut number = parent.clone(); @@ -471,13 +471,14 @@ fn get_last_link(links: &mut [SummaryItem]) -> Result<(usize, &mut Link)> { /// Removes the styling from a list of Markdown events and returns just the /// plain text. -fn stringify_events(events: Vec<Event>) -> String { +fn stringify_events(events: Vec<Event<'_>>) -> String { events .into_iter() .filter_map(|t| match t { - Event::Text(text) => Some(text.into_owned()), + Event::Text(text) | Event::Code(text) => Some(text.into_string()), _ => None, - }).collect() + }) + .collect() } /// A section number like "1.2.3", basically just a newtype'd `Vec<u32>` with @@ -486,7 +487,7 @@ fn stringify_events(events: Vec<Event>) -> String { pub struct SectionNumber(pub Vec<u32>); impl Display for SectionNumber { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if self.0.is_empty() { write!(f, "0") } else { @@ -628,7 +629,7 @@ mod tests { let _ = parser.stream.next(); // skip past start of paragraph let href = match parser.stream.next() { - Some(Event::Start(Tag::Link(href, _))) => href.to_string(), + Some(Event::Start(Tag::Link(_type, href, _title))) => href.to_string(), other => panic!("Unreachable, {:?}", other), }; diff --git a/vendor/mdbook/src/cmd/build.rs b/vendor/mdbook/src/cmd/build.rs index 4a5abbc0f3..d1c663026d 100644 --- a/vendor/mdbook/src/cmd/build.rs +++ b/vendor/mdbook/src/cmd/build.rs @@ -1,7 +1,7 @@ +use crate::{get_book_dir, open}; use clap::{App, ArgMatches, SubCommand}; use mdbook::errors::Result; use mdbook::MDBook; -use {get_book_dir, open}; // Create clap subcommand arguments pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { @@ -11,10 +11,12 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\ Relative paths are interpreted relative to the book's root directory.{n}\ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'", - ).arg_from_usage( + ) + .arg_from_usage( "[dir] 'Root directory for the book{n}\ (Defaults to the Current Directory when omitted)'", - ).arg_from_usage("-o, --open 'Opens the compiled book in a web browser'") + ) + .arg_from_usage("-o, --open 'Opens the compiled book in a web browser'") } // Build command implementation diff --git a/vendor/mdbook/src/cmd/clean.rs b/vendor/mdbook/src/cmd/clean.rs index fba49be842..07c2fbc63d 100644 --- a/vendor/mdbook/src/cmd/clean.rs +++ b/vendor/mdbook/src/cmd/clean.rs @@ -1,5 +1,5 @@ +use crate::get_book_dir; use clap::{App, ArgMatches, SubCommand}; -use get_book_dir; use mdbook::errors::*; use mdbook::MDBook; use std::fs; @@ -13,14 +13,15 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { Relative paths are interpreted relative to the book's root directory.{n}\ Running this command deletes this directory.{n}\ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'", - ).arg_from_usage( + ) + .arg_from_usage( "[dir] 'Root directory for the book{n}\ (Defaults to the Current Directory when omitted)'", ) } // Clean command implementation -pub fn execute(args: &ArgMatches) -> ::mdbook::errors::Result<()> { +pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> { let book_dir = get_book_dir(args); let book = MDBook::load(&book_dir)?; diff --git a/vendor/mdbook/src/cmd/init.rs b/vendor/mdbook/src/cmd/init.rs index c6bba9d503..1a49f0d335 100644 --- a/vendor/mdbook/src/cmd/init.rs +++ b/vendor/mdbook/src/cmd/init.rs @@ -1,5 +1,5 @@ +use crate::get_book_dir; use clap::{App, ArgMatches, SubCommand}; -use get_book_dir; use mdbook::config; use mdbook::errors::Result; use mdbook::MDBook; @@ -15,7 +15,8 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { .arg_from_usage( "[dir] 'Directory to create the book in{n}\ (Defaults to the Current Directory when omitted)'", - ).arg_from_usage("--theme 'Copies the default theme into your source folder'") + ) + .arg_from_usage("--theme 'Copies the default theme into your source folder'") .arg_from_usage("--force 'Skips confirmation prompts'") } diff --git a/vendor/mdbook/src/cmd/serve.rs b/vendor/mdbook/src/cmd/serve.rs index 9659d820fc..3c8c53dc73 100644 --- a/vendor/mdbook/src/cmd/serve.rs +++ b/vendor/mdbook/src/cmd/serve.rs @@ -1,18 +1,11 @@ -extern crate iron; -extern crate staticfile; -extern crate ws; - -use self::iron::{ - status, AfterMiddleware, Chain, Iron, IronError, IronResult, Request, Response, Set, -}; #[cfg(feature = "watch")] use super::watch; +use crate::{get_book_dir, open}; use clap::{App, Arg, ArgMatches, SubCommand}; +use iron::{status, AfterMiddleware, Chain, Iron, IronError, IronResult, Request, Response, Set}; use mdbook::errors::*; use mdbook::utils; use mdbook::MDBook; -use std; -use {get_book_dir, open}; struct ErrorRecover; @@ -115,8 +108,8 @@ pub fn execute(args: &ArgMatches) -> Result<()> { } #[cfg(feature = "watch")] - watch::trigger_on_change(&book, move |path, book_dir| { - info!("File changed: {:?}", path); + watch::trigger_on_change(&book, move |paths, book_dir| { + info!("Files changed: {:?}", paths); info!("Building book..."); // FIXME: This area is really ugly because we need to re-set livereload :( @@ -126,7 +119,8 @@ pub fn execute(args: &ArgMatches) -> Result<()> { b.config .set("output.html.livereload-url", &livereload_url)?; Ok(b) - }).and_then(|b| b.build()); + }) + .and_then(|b| b.build()); if let Err(e) = result { error!("Unable to load the book"); diff --git a/vendor/mdbook/src/cmd/test.rs b/vendor/mdbook/src/cmd/test.rs index 63e1910db2..f6d97aa656 100644 --- a/vendor/mdbook/src/cmd/test.rs +++ b/vendor/mdbook/src/cmd/test.rs @@ -1,5 +1,5 @@ +use crate::get_book_dir; use clap::{App, Arg, ArgMatches, SubCommand}; -use get_book_dir; use mdbook::errors::Result; use mdbook::MDBook; @@ -31,7 +31,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { pub fn execute(args: &ArgMatches) -> Result<()> { let library_paths: Vec<&str> = args .values_of("library-path") - .map(|v| v.collect()) + .map(std::iter::Iterator::collect) .unwrap_or_default(); let book_dir = get_book_dir(args); let mut book = MDBook::load(&book_dir)?; diff --git a/vendor/mdbook/src/cmd/watch.rs b/vendor/mdbook/src/cmd/watch.rs index d800ae7de5..bf903f90a7 100644 --- a/vendor/mdbook/src/cmd/watch.rs +++ b/vendor/mdbook/src/cmd/watch.rs @@ -1,14 +1,13 @@ -extern crate notify; - -use self::notify::Watcher; +use crate::{get_book_dir, open}; use clap::{App, ArgMatches, SubCommand}; use mdbook::errors::Result; use mdbook::utils; use mdbook::MDBook; -use std::path::Path; +use notify::Watcher; +use std::path::{Path, PathBuf}; use std::sync::mpsc::channel; +use std::thread::sleep; use std::time::Duration; -use {get_book_dir, open}; // Create clap subcommand arguments pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { @@ -18,10 +17,12 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> { "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\ Relative paths are interpreted relative to the book's root directory.{n}\ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'", - ).arg_from_usage( + ) + .arg_from_usage( "[dir] 'Root directory for the book{n}\ (Defaults to the Current Directory when omitted)'", - ).arg_from_usage("-o, --open 'Open the compiled book in a web browser'") + ) + .arg_from_usage("-o, --open 'Open the compiled book in a web browser'") } // Watch command implementation @@ -34,8 +35,8 @@ pub fn execute(args: &ArgMatches) -> Result<()> { open(book.build_dir_for("html").join("index.html")); } - trigger_on_change(&book, |path, book_dir| { - info!("File changed: {:?}\nBuilding book...\n", path); + trigger_on_change(&book, |paths, book_dir| { + info!("Files changed: {:?}\nBuilding book...\n", paths); let result = MDBook::load(&book_dir).and_then(|b| b.build()); if let Err(e) = result { @@ -50,10 +51,10 @@ pub fn execute(args: &ArgMatches) -> Result<()> { /// Calls the closure when a book source file is changed, blocking indefinitely. pub fn trigger_on_change<F>(book: &MDBook, closure: F) where - F: Fn(&Path, &Path), + F: Fn(Vec<PathBuf>, &Path), { - use self::notify::DebouncedEvent::*; - use self::notify::RecursiveMode::*; + use notify::DebouncedEvent::*; + use notify::RecursiveMode::*; // Create a channel to receive the events. let (tx, rx) = channel(); @@ -62,14 +63,14 @@ where Ok(w) => w, Err(e) => { error!("Error while trying to watch the files:\n\n\t{:?}", e); - ::std::process::exit(1) + std::process::exit(1) } }; // Add the source directory to the watcher if let Err(e) = watcher.watch(book.source_dir(), Recursive) { error!("Error while watching {:?}:\n {:?}", book.source_dir(), e); - ::std::process::exit(1); + std::process::exit(1); }; let _ = watcher.watch(book.theme_dir(), Recursive); @@ -79,13 +80,24 @@ where info!("Listening for changes..."); - for event in rx.iter() { - debug!("Received filesystem event: {:?}", event); - match event { - Create(path) | Write(path) | Remove(path) | Rename(_, path) => { - closure(&path, &book.root); - } - _ => {} - } + loop { + let first_event = rx.recv().unwrap(); + sleep(Duration::from_millis(50)); + let other_events = rx.try_iter(); + + let all_events = std::iter::once(first_event).chain(other_events); + + let paths = all_events + .filter_map(|event| { + debug!("Received filesystem event: {:?}", event); + + match event { + Create(path) | Write(path) | Remove(path) | Rename(_, path) => Some(path), + _ => None, + } + }) + .collect(); + + closure(paths, &book.root); } } diff --git a/vendor/mdbook/src/config.rs b/vendor/mdbook/src/config.rs index c6b370949d..59ae8ad049 100644 --- a/vendor/mdbook/src/config.rs +++ b/vendor/mdbook/src/config.rs @@ -3,16 +3,15 @@ //! The main entrypoint of the `config` module is the `Config` struct. This acts //! essentially as a bag of configuration information, with a couple //! pre-determined tables (`BookConfig` and `BuildConfig`) as well as support -//! for arbitrary data which is exposed to plugins and alternate backends. +//! for arbitrary data which is exposed to plugins and alternative backends. //! //! //! # Examples //! //! ```rust -//! # extern crate mdbook; //! # use mdbook::errors::*; -//! # extern crate toml; //! use std::path::PathBuf; +//! use std::str::FromStr; //! use mdbook::Config; //! use toml::Value; //! @@ -51,18 +50,18 @@ #![deny(missing_docs)] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde_json; use std::env; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; +use std::str::FromStr; use toml::value::Table; use toml::{self, Value}; use toml_query::delete::TomlValueDeleteExt; use toml_query::insert::TomlValueInsertExt; use toml_query::read::TomlValueReadExt; -use errors::*; +use crate::errors::*; /// The overall configuration object for MDBook, essentially an in-memory /// representation of `book.toml`. @@ -75,12 +74,16 @@ pub struct Config { rest: Value, } -impl Config { +impl FromStr for Config { + type Err = Error; + /// Load a `Config` from some string. - pub fn from_str(src: &str) -> Result<Config> { + fn from_str(src: &str) -> Result<Self> { toml::from_str(src).chain_err(|| Error::from("Invalid configuration file")) } +} +impl Config { /// Load the configuration file from disk. pub fn from_disk<P: AsRef<Path>>(config_file: P) -> Result<Config> { let mut buffer = String::new(); @@ -203,7 +206,9 @@ impl Config { } else if index.starts_with("build.") { self.build.update_value(&index[6..], value); } else { - self.rest.insert(index, value)?; + self.rest + .insert(index, value) + .map_err(|e| ErrorKind::TomlQueryError(e))?; } Ok(()) @@ -212,13 +217,13 @@ impl Config { /// Get the table associated with a particular renderer. pub fn get_renderer<I: AsRef<str>>(&self, index: I) -> Option<&Table> { let key = format!("output.{}", index.as_ref()); - self.get(&key).and_then(|v| v.as_table()) + self.get(&key).and_then(Value::as_table) } /// Get the table associated with a particular preprocessor. pub fn get_preprocessor<I: AsRef<str>>(&self, index: I) -> Option<&Table> { let key = format!("preprocessor.{}", index.as_ref()); - self.get(&key).and_then(|v| v.as_table()) + self.get(&key).and_then(Value::as_table) } fn from_legacy(mut table: Value) -> Config { @@ -265,7 +270,7 @@ impl Default for Config { } } impl<'de> Deserialize<'de> for Config { - fn deserialize<D: Deserializer<'de>>(de: D) -> ::std::result::Result<Self, D::Error> { + fn deserialize<D: Deserializer<'de>>(de: D) -> std::result::Result<Self, D::Error> { let raw = Value::deserialize(de)?; if is_legacy_format(&raw) { @@ -309,7 +314,7 @@ impl<'de> Deserialize<'de> for Config { } impl Serialize for Config { - fn serialize<S: Serializer>(&self, s: S) -> ::std::result::Result<S::Ok, S::Error> { + fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> { use serde::ser::Error; let mut table = self.rest.clone(); @@ -560,7 +565,7 @@ impl<'de, T> Updateable<'de> for T where T: Serialize + Deserialize<'de> {} mod tests { use super::*; - const COMPLEX_CONFIG: &'static str = r#" + const COMPLEX_CONFIG: &str = r#" [book] title = "Some Book" authors = ["Michael-F-Bryan <michaelfbryan@gmail.com>"] @@ -586,9 +591,9 @@ mod tests { editable = true editor = "ace" - [preprocess.first] + [preprocessor.first] - [preprocess.second] + [preprocessor.second] "#; #[test] @@ -601,7 +606,6 @@ mod tests { description: Some(String::from("A completely useless book")), multilingual: true, src: PathBuf::from("source"), - ..Default::default() }; let build_should_be = BuildConfig { build_dir: PathBuf::from("outputs"), @@ -658,10 +662,10 @@ mod tests { assert_eq!(got, should_be); - let baz: Vec<bool> = cfg.get_deserialized("output.random.baz").unwrap(); + let got_baz: Vec<bool> = cfg.get_deserialized("output.random.baz").unwrap(); let baz_should_be = vec![true, true, false]; - assert_eq!(baz, baz_should_be); + assert_eq!(got_baz, baz_should_be); } #[test] @@ -753,7 +757,7 @@ mod tests { for (src, should_be) in inputs { let got = parse_env(src); - let should_be = should_be.map(|s| s.to_string()); + let should_be = should_be.map(ToString::to_string); assert_eq!(got, should_be); } @@ -783,6 +787,7 @@ mod tests { } #[test] + #[allow(clippy::approx_constant)] fn update_config_using_env_var_and_complex_value() { let mut cfg = Config::default(); let key = "foo-bar.baz"; diff --git a/vendor/mdbook/src/lib.rs b/vendor/mdbook/src/lib.rs index 028a2ba87b..1a1ce85c34 100644 --- a/vendor/mdbook/src/lib.rs +++ b/vendor/mdbook/src/lib.rs @@ -81,27 +81,18 @@ //! [`Config`]: config/struct.Config.html #![deny(missing_docs)] +#![deny(rust_2018_idioms)] #[macro_use] extern crate error_chain; -extern crate handlebars; -extern crate itertools; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate memchr; -extern crate pulldown_cmark; -extern crate regex; -extern crate serde; #[macro_use] extern crate serde_derive; #[macro_use] extern crate serde_json; -extern crate shlex; -extern crate tempfile; -extern crate toml; -extern crate toml_query; #[cfg(test)] #[macro_use] @@ -120,31 +111,27 @@ pub mod utils; /// compatibility checks. pub const MDBOOK_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub use book::BookItem; -pub use book::MDBook; -pub use config::Config; -pub use renderer::Renderer; +pub use crate::book::BookItem; +pub use crate::book::MDBook; +pub use crate::config::Config; +pub use crate::renderer::Renderer; /// The error types used through out this crate. pub mod errors { use std::path::PathBuf; - error_chain!{ + error_chain! { foreign_links { - Io(::std::io::Error) #[doc = "A wrapper around `std::io::Error`"]; - HandlebarsRender(::handlebars::RenderError) #[doc = "Handlebars rendering failed"]; - HandlebarsTemplate(Box<::handlebars::TemplateError>) #[doc = "Unable to parse the template"]; - Utf8(::std::string::FromUtf8Error) #[doc = "Invalid UTF-8"]; - SerdeJson(::serde_json::Error) #[doc = "JSON conversion failed"]; - } - - links { - TomlQuery(::toml_query::error::Error, ::toml_query::error::ErrorKind) #[doc = "A TomlQuery error"]; + Io(std::io::Error) #[doc = "A wrapper around `std::io::Error`"]; + HandlebarsRender(handlebars::RenderError) #[doc = "Handlebars rendering failed"]; + HandlebarsTemplate(Box<handlebars::TemplateError>) #[doc = "Unable to parse the template"]; + Utf8(std::string::FromUtf8Error) #[doc = "Invalid UTF-8"]; + SerdeJson(serde_json::Error) #[doc = "JSON conversion failed"]; } errors { /// A subprocess exited with an unsuccessful return code. - Subprocess(message: String, output: ::std::process::Output) { + Subprocess(message: String, output: std::process::Output) { description("A subprocess failed") display("{}: {}", message, String::from_utf8_lossy(&output.stdout)) } @@ -160,12 +147,18 @@ pub mod errors { description("Reserved Filename") display("{} is reserved for internal use", filename.display()) } + + /// Error with a TOML file. + TomlQueryError(inner: toml_query::error::Error) { + description("toml_query error") + display("{}", inner) + } } } // Box to halve the size of Error - impl From<::handlebars::TemplateError> for Error { - fn from(e: ::handlebars::TemplateError) -> Error { + impl From<handlebars::TemplateError> for Error { + fn from(e: handlebars::TemplateError) -> Error { From::from(Box::new(e)) } } diff --git a/vendor/mdbook/src/main.rs b/vendor/mdbook/src/main.rs index dec89cf346..14aad67a8c 100644 --- a/vendor/mdbook/src/main.rs +++ b/vendor/mdbook/src/main.rs @@ -1,12 +1,7 @@ -extern crate chrono; #[macro_use] extern crate clap; -extern crate env_logger; -extern crate error_chain; #[macro_use] extern crate log; -extern crate mdbook; -extern crate open; use chrono::Local; use clap::{App, AppSettings, ArgMatches}; @@ -20,19 +15,19 @@ use std::path::{Path, PathBuf}; mod cmd; -const NAME: &str = "mdBook"; const VERSION: &str = concat!("v", crate_version!()); fn main() { init_logger(); // Create a list of valid arguments and sub-commands - let app = App::new(NAME) - .about("Creates a book from markdown files") + let app = App::new(crate_name!()) + .about(crate_description!()) .author("Mathieu David <mathieudavid@mathieudavid.org>") .version(VERSION) .setting(AppSettings::GlobalVersion) .setting(AppSettings::ArgRequiredElseHelp) + .setting(AppSettings::ColoredHelp) .after_help( "For more information about a specific command, try `mdbook <command> --help`\n\ The source code for mdBook is available at: https://github.com/rust-lang-nursery/mdBook", @@ -63,7 +58,7 @@ fn main() { if let Err(e) = res { utils::log_backtrace(&e); - ::std::process::exit(101); + std::process::exit(101); } } @@ -82,7 +77,7 @@ fn init_logger() { }); if let Ok(var) = env::var("RUST_LOG") { - builder.parse(&var); + builder.parse_filters(&var); } else { // if no RUST_LOG provided, default to logging at the Info level builder.filter(None, LevelFilter::Info); diff --git a/vendor/mdbook/src/preprocess/cmd.rs b/vendor/mdbook/src/preprocess/cmd.rs index d548d90e54..b16d365a8f 100644 --- a/vendor/mdbook/src/preprocess/cmd.rs +++ b/vendor/mdbook/src/preprocess/cmd.rs @@ -1,7 +1,6 @@ use super::{Preprocessor, PreprocessorContext}; -use book::Book; -use errors::*; -use serde_json; +use crate::book::Book; +use crate::errors::*; use shlex::Shlex; use std::io::{self, Read, Write}; use std::process::{Child, Command, Stdio}; @@ -168,8 +167,8 @@ impl Preprocessor for CmdPreprocessor { #[cfg(test)] mod tests { use super::*; + use crate::MDBook; use std::path::Path; - use MDBook; fn book_example() -> MDBook { let example = Path::new(env!("CARGO_MANIFEST_DIR")).join("book-example"); diff --git a/vendor/mdbook/src/preprocess/index.rs b/vendor/mdbook/src/preprocess/index.rs index a881851879..f3256b81f2 100644 --- a/vendor/mdbook/src/preprocess/index.rs +++ b/vendor/mdbook/src/preprocess/index.rs @@ -1,13 +1,14 @@ use regex::Regex; use std::path::Path; -use errors::*; +use crate::errors::*; use super::{Preprocessor, PreprocessorContext}; -use book::{Book, BookItem}; +use crate::book::{Book, BookItem}; /// A preprocessor for converting file name `README.md` to `index.md` since /// `README.md` is the de facto index file in markdown-based documentation. +#[derive(Default)] pub struct IndexPreprocessor; impl IndexPreprocessor { @@ -45,7 +46,10 @@ impl Preprocessor for IndexPreprocessor { fn warn_readme_name_conflict<P: AsRef<Path>>(readme_path: P, index_path: P) { let file_name = readme_path.as_ref().file_name().unwrap_or_default(); - let parent_dir = index_path.as_ref().parent().unwrap_or(index_path.as_ref()); + let parent_dir = index_path + .as_ref() + .parent() + .unwrap_or_else(|| index_path.as_ref()); warn!( "It seems that there are both {:?} and index.md under \"{}\".", file_name, @@ -67,7 +71,7 @@ fn is_readme_file<P: AsRef<Path>>(path: P) -> bool { RE.is_match( path.as_ref() .file_stem() - .and_then(|s| s.to_str()) + .and_then(std::ffi::OsStr::to_str) .unwrap_or_default(), ) } diff --git a/vendor/mdbook/src/preprocess/links.rs b/vendor/mdbook/src/preprocess/links.rs index 90a057b0ec..6ee5667a63 100644 --- a/vendor/mdbook/src/preprocess/links.rs +++ b/vendor/mdbook/src/preprocess/links.rs @@ -1,18 +1,19 @@ -use errors::*; +use crate::errors::*; +use crate::utils::fs::file_to_string; +use crate::utils::take_lines; use regex::{CaptureMatches, Captures, Regex}; use std::ops::{Range, RangeFrom, RangeFull, RangeTo}; use std::path::{Path, PathBuf}; -use utils::fs::file_to_string; -use utils::take_lines; use super::{Preprocessor, PreprocessorContext}; -use book::{Book, BookItem}; +use crate::book::{Book, BookItem}; const ESCAPE_CHAR: char = '\\'; const MAX_LINK_NESTED_DEPTH: usize = 10; /// A preprocessor for expanding the `{{# playpen}}` and `{{# include}}` /// helpers in a chapter. +#[derive(Default)] pub struct LinkPreprocessor; impl LinkPreprocessor { @@ -143,17 +144,19 @@ fn parse_include_path(path: &str) -> LinkType<'static> { match start { Some(start) => match end { Some(end) => LinkType::IncludeRange(path, Range { start, end }), - None => if has_end { - LinkType::IncludeRangeFrom(path, RangeFrom { start }) - } else { - LinkType::IncludeRange( - path, - Range { - start, - end: start + 1, - }, - ) - }, + None => { + if has_end { + LinkType::IncludeRangeFrom(path, RangeFrom { start }) + } else { + LinkType::IncludeRange( + path, + Range { + start, + end: start + 1, + }, + ) + } + } }, None => match end { Some(end) => LinkType::IncludeRangeTo(path, RangeTo { end }), @@ -291,7 +294,7 @@ impl<'a> Iterator for LinkIter<'a> { } } -fn find_links(contents: &str) -> LinkIter { +fn find_links(contents: &str) -> LinkIter<'_> { // lazily compute following regex // r"\\\{\{#.*\}\}|\{\{#([a-zA-Z0-9]+)\s*([a-zA-Z0-9_.\-:/\\\s]+)\}\}")?; lazy_static! { @@ -304,7 +307,8 @@ fn find_links(contents: &str) -> LinkIter { \s+ # separating whitespace ([a-zA-Z0-9\s_.\-:/\\]+) # link target path and space separated properties \s*\}\} # whitespace and link closing parens" - ).unwrap(); + ) + .unwrap(); } LinkIter(RE.captures_iter(contents)) } diff --git a/vendor/mdbook/src/preprocess/mod.rs b/vendor/mdbook/src/preprocess/mod.rs index 1a30540880..ebc343115a 100644 --- a/vendor/mdbook/src/preprocess/mod.rs +++ b/vendor/mdbook/src/preprocess/mod.rs @@ -8,9 +8,9 @@ mod cmd; mod index; mod links; -use book::Book; -use config::Config; -use errors::*; +use crate::book::Book; +use crate::config::Config; +use crate::errors::*; use std::path::PathBuf; @@ -37,7 +37,7 @@ impl PreprocessorContext { root, config, renderer, - mdbook_version: ::MDBOOK_VERSION.to_string(), + mdbook_version: crate::MDBOOK_VERSION.to_string(), __non_exhaustive: (), } } diff --git a/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs b/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs index b5ef228d34..e4c2faf499 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs @@ -1,10 +1,10 @@ -use book::{Book, BookItem}; -use config::{Config, HtmlConfig, Playpen}; -use errors::*; -use renderer::html_handlebars::helpers; -use renderer::{RenderContext, Renderer}; -use theme::{self, playpen_editor, Theme}; -use utils; +use crate::book::{Book, BookItem}; +use crate::config::{Config, HtmlConfig, Playpen}; +use crate::errors::*; +use crate::renderer::html_handlebars::helpers; +use crate::renderer::{RenderContext, Renderer}; +use crate::theme::{self, playpen_editor, Theme}; +use crate::utils; use std::collections::BTreeMap; use std::collections::HashMap; @@ -13,7 +13,6 @@ use std::path::{Path, PathBuf}; use handlebars::Handlebars; use regex::{Captures, Regex}; -use serde_json; #[derive(Default)] pub struct HtmlHandlebars; @@ -26,7 +25,7 @@ impl HtmlHandlebars { fn render_item( &self, item: &BookItem, - mut ctx: RenderItemContext, + mut ctx: RenderItemContext<'_>, print_content: &mut String, ) -> Result<()> { // FIXME: This should be made DRY-er and rely less on mutable state @@ -36,7 +35,11 @@ impl HtmlHandlebars { let string_path = ch.path.parent().unwrap().display().to_string(); - let fixed_content = utils::render_markdown_with_base(&ch.content, ctx.html_config.curly_quotes, &string_path); + let fixed_content = utils::render_markdown_with_base( + &ch.content, + ctx.html_config.curly_quotes, + &string_path, + ); print_content.push_str(&fixed_content); // Update the context with data for this file @@ -82,7 +85,7 @@ impl HtmlHandlebars { utils::fs::write_file(&ctx.destination, &filepath, rendered.as_bytes())?; if ctx.is_index { - ctx.data.insert("path".to_owned(), json!("index.html")); + ctx.data.insert("path".to_owned(), json!("index.md")); ctx.data.insert("path_to_root".to_owned(), json!("")); let rendered_index = ctx.handlebars.render("index", &ctx.data)?; let rendered_index = self.post_process(rendered_index, &ctx.html_config.playpen); @@ -109,7 +112,7 @@ impl HtmlHandlebars { theme: &Theme, html_config: &HtmlConfig, ) -> Result<()> { - use utils::fs::write_file; + use crate::utils::fs::write_file; write_file( destination, @@ -425,13 +428,7 @@ fn make_data( for script in &html.additional_js { match script.strip_prefix(root) { Ok(p) => js.push(p.to_str().expect("Could not convert to str")), - Err(_) => js.push( - script - .file_name() - .expect("File has a file name") - .to_str() - .expect("Could not convert to str"), - ), + Err(_) => js.push(script.to_str().expect("Could not convert to str")), } } data.insert("additional_js".to_owned(), json!(js)); @@ -499,25 +496,26 @@ fn make_data( Ok(data) } -/// Goes through the rendered HTML, making sure all header tags are wrapped in -/// an anchor so people can link to sections directly. +/// Goes through the rendered HTML, making sure all header tags have +/// an anchor respectively so people can link to sections directly. fn build_header_links(html: &str) -> String { let regex = Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap(); let mut id_counter = HashMap::new(); regex - .replace_all(html, |caps: &Captures| { + .replace_all(html, |caps: &Captures<'_>| { let level = caps[1] .parse() .expect("Regex should ensure we only ever get numbers here"); - wrap_header_with_link(level, &caps[2], &mut id_counter) - }).into_owned() + insert_link_into_header(level, &caps[2], &mut id_counter) + }) + .into_owned() } -/// Wraps a single header tag with a link, making sure each tag gets its own +/// Insert a sinle link into a header, making sure each link gets its own /// unique ID by appending an auto-incremented number (if necessary). -fn wrap_header_with_link( +fn insert_link_into_header( level: usize, content: &str, id_counter: &mut HashMap<String, usize>, @@ -534,7 +532,7 @@ fn wrap_header_with_link( *id_count += 1; format!( - r##"<a class="header" href="#{id}" id="{id}"><h{level}>{text}</h{level}></a>"##, + r##"<h{level}><a class="header" href="#{id}" id="{id}">{text}</a></h{level}>"##, level = level, id = id, text = content @@ -552,7 +550,7 @@ fn wrap_header_with_link( fn fix_code_blocks(html: &str) -> String { let regex = Regex::new(r##"<code([^>]+)class="([^"]+)"([^>]*)>"##).unwrap(); regex - .replace_all(html, |caps: &Captures| { + .replace_all(html, |caps: &Captures<'_>| { let before = &caps[1]; let classes = &caps[2].replace(",", " "); let after = &caps[3]; @@ -563,13 +561,14 @@ fn fix_code_blocks(html: &str) -> String { classes = classes, after = after ) - }).into_owned() + }) + .into_owned() } fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String { let regex = Regex::new(r##"((?s)<code[^>]?class="([^"]+)".*?>(.*?)</code>)"##).unwrap(); regex - .replace_all(html, |caps: &Captures| { + .replace_all(html, |caps: &Captures<'_>| { let text = &caps[1]; let classes = &caps[2]; let code = &caps[3]; @@ -599,7 +598,8 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String { // not language-rust, so no-op text.to_owned() } - }).into_owned() + }) + .into_owned() } fn partition_source(s: &str) -> (String, String) { @@ -609,7 +609,7 @@ fn partition_source(s: &str) -> (String, String) { for line in s.lines() { let trimline = line.trim(); - let header = trimline.chars().all(|c| c.is_whitespace()) || trimline.starts_with("#!["); + let header = trimline.chars().all(char::is_whitespace) || trimline.starts_with("#!["); if !header || after_header { after_header = true; after.push_str(line); @@ -640,27 +640,27 @@ mod tests { let inputs = vec![ ( "blah blah <h1>Foo</h1>", - r##"blah blah <a class="header" href="#foo" id="foo"><h1>Foo</h1></a>"##, + r##"blah blah <h1><a class="header" href="#foo" id="foo">Foo</a></h1>"##, ), ( "<h1>Foo</h1>", - r##"<a class="header" href="#foo" id="foo"><h1>Foo</h1></a>"##, + r##"<h1><a class="header" href="#foo" id="foo">Foo</a></h1>"##, ), ( "<h3>Foo^bar</h3>", - r##"<a class="header" href="#foobar" id="foobar"><h3>Foo^bar</h3></a>"##, + r##"<h3><a class="header" href="#foobar" id="foobar">Foo^bar</a></h3>"##, ), ( "<h4></h4>", - r##"<a class="header" href="#" id=""><h4></h4></a>"##, + r##"<h4><a class="header" href="#" id=""></a></h4>"##, ), ( "<h4><em>Hï</em></h4>", - r##"<a class="header" href="#hï" id="hï"><h4><em>Hï</em></h4></a>"##, + r##"<h4><a class="header" href="#hï" id="hï"><em>Hï</em></a></h4>"##, ), ( "<h1>Foo</h1><h3>Foo</h3>", - r##"<a class="header" href="#foo" id="foo"><h1>Foo</h1></a><a class="header" href="#foo-1" id="foo-1"><h3>Foo</h3></a>"##, + r##"<h1><a class="header" href="#foo" id="foo">Foo</a></h1><h3><a class="header" href="#foo-1" id="foo-1">Foo</a></h3>"##, ), ]; diff --git a/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs b/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs index 0e55100406..4d162af736 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs @@ -2,9 +2,8 @@ use std::collections::BTreeMap; use std::path::Path; use handlebars::{Context, Handlebars, Helper, Output, RenderContext, RenderError, Renderable}; -use serde_json; -use utils; +use crate::utils; type StringMap = BTreeMap<String, String>; @@ -47,7 +46,7 @@ impl Target { fn find_chapter( ctx: &Context, - rc: &mut RenderContext, + rc: &mut RenderContext<'_>, target: Target, ) -> Result<Option<StringMap>, RenderError> { debug!("Get data from context"); @@ -86,11 +85,11 @@ fn find_chapter( } fn render( - _h: &Helper, + _h: &Helper<'_, '_>, r: &Handlebars, ctx: &Context, - rc: &mut RenderContext, - out: &mut Output, + rc: &mut RenderContext<'_>, + out: &mut dyn Output, chapter: &StringMap, ) -> Result<(), RenderError> { trace!("Creating BTreeMap to inject in context"); @@ -137,11 +136,11 @@ fn render( } pub fn previous( - _h: &Helper, + _h: &Helper<'_, '_>, r: &Handlebars, ctx: &Context, - rc: &mut RenderContext, - out: &mut Output, + rc: &mut RenderContext<'_>, + out: &mut dyn Output, ) -> Result<(), RenderError> { trace!("previous (handlebars helper)"); @@ -153,11 +152,11 @@ pub fn previous( } pub fn next( - _h: &Helper, + _h: &Helper<'_, '_>, r: &Handlebars, ctx: &Context, - rc: &mut RenderContext, - out: &mut Output, + rc: &mut RenderContext<'_>, + out: &mut dyn Output, ) -> Result<(), RenderError> { trace!("next (handlebars helper)"); @@ -172,29 +171,29 @@ pub fn next( mod tests { use super::*; - static TEMPLATE: &'static str = + static TEMPLATE: &str = "{{#previous}}{{title}}: {{link}}{{/previous}}|{{#next}}{{title}}: {{link}}{{/next}}"; #[test] fn test_next_previous() { let data = json!({ - "name": "two", - "path": "two.path", - "chapters": [ - { - "name": "one", - "path": "one.path" - }, - { - "name": "two", - "path": "two.path", - }, - { - "name": "three", - "path": "three.path" - } - ] - }); + "name": "two", + "path": "two.path", + "chapters": [ + { + "name": "one", + "path": "one.path" + }, + { + "name": "two", + "path": "two.path", + }, + { + "name": "three", + "path": "three.path" + } + ] + }); let mut h = Handlebars::new(); h.register_helper("previous", Box::new(previous)); @@ -209,23 +208,23 @@ mod tests { #[test] fn test_first() { let data = json!({ - "name": "one", - "path": "one.path", - "chapters": [ - { - "name": "one", - "path": "one.path" - }, - { - "name": "two", - "path": "two.path", - }, - { - "name": "three", - "path": "three.path" - } - ] - }); + "name": "one", + "path": "one.path", + "chapters": [ + { + "name": "one", + "path": "one.path" + }, + { + "name": "two", + "path": "two.path", + }, + { + "name": "three", + "path": "three.path" + } + ] + }); let mut h = Handlebars::new(); h.register_helper("previous", Box::new(previous)); @@ -239,23 +238,23 @@ mod tests { #[test] fn test_last() { let data = json!({ - "name": "three", - "path": "three.path", - "chapters": [ - { - "name": "one", - "path": "one.path" - }, - { - "name": "two", - "path": "two.path", - }, - { - "name": "three", - "path": "three.path" - } - ] - }); + "name": "three", + "path": "three.path", + "chapters": [ + { + "name": "one", + "path": "one.path" + }, + { + "name": "two", + "path": "two.path", + }, + { + "name": "three", + "path": "three.path" + } + ] + }); let mut h = Handlebars::new(); h.register_helper("previous", Box::new(previous)); diff --git a/vendor/mdbook/src/renderer/html_handlebars/helpers/theme.rs b/vendor/mdbook/src/renderer/html_handlebars/helpers/theme.rs index 24c0dda1f3..a42c2f91d6 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/helpers/theme.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/helpers/theme.rs @@ -1,20 +1,17 @@ use handlebars::{Context, Handlebars, Helper, Output, RenderContext, RenderError}; pub fn theme_option( - h: &Helper, + h: &Helper<'_, '_>, _r: &Handlebars, ctx: &Context, - rc: &mut RenderContext, - out: &mut Output, + rc: &mut RenderContext<'_>, + out: &mut dyn Output, ) -> Result<(), RenderError> { trace!("theme_option (handlebars helper)"); - let param = h - .param(0) - .and_then(|v| v.value().as_str()) - .ok_or(RenderError::new( - "Param 0 with String type is required for theme_option helper.", - ))?; + let param = h.param(0).and_then(|v| v.value().as_str()).ok_or_else(|| { + RenderError::new("Param 0 with String type is required for theme_option helper.") + })?; let theme_name = rc .evaluate_absolute(ctx, "default_theme", true)? diff --git a/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs b/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs index 190a347071..3fdec59965 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/helpers/toc.rs @@ -1,11 +1,10 @@ use std::collections::BTreeMap; use std::path::Path; -use utils; +use crate::utils; use handlebars::{Context, Handlebars, Helper, HelperDef, Output, RenderContext, RenderError}; -use pulldown_cmark::{html, Event, Parser, Tag}; -use serde_json; +use pulldown_cmark::{html, Event, Parser}; // Handlebars helper to construct TOC #[derive(Clone, Copy)] @@ -16,11 +15,11 @@ pub struct RenderToc { impl HelperDef for RenderToc { fn call<'reg: 'rc, 'rc>( &self, - _h: &Helper, - _: &Handlebars, - ctx: &Context, - rc: &mut RenderContext, - out: &mut Output, + _h: &Helper<'reg, 'rc>, + _r: &'reg Handlebars, + ctx: &'rc Context, + rc: &mut RenderContext<'reg>, + out: &mut dyn Output, ) -> Result<(), RenderError> { // get value from context data // rc.get_path() is current json parent path, you should always use it like this @@ -118,10 +117,7 @@ impl HelperDef for RenderToc { // filter all events that are not inline code blocks let parser = Parser::new(name).filter(|event| match *event { - Event::Start(Tag::Code) - | Event::End(Tag::Code) - | Event::InlineHtml(_) - | Event::Text(_) => true, + Event::Code(_) | Event::InlineHtml(_) | Event::Text(_) => true, _ => false, }); diff --git a/vendor/mdbook/src/renderer/html_handlebars/search.rs b/vendor/mdbook/src/renderer/html_handlebars/search.rs index c27977e198..46327bda40 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/search.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/search.rs @@ -1,19 +1,15 @@ -extern crate ammonia; -extern crate elasticlunr; - use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::path::Path; -use self::elasticlunr::Index; +use elasticlunr::Index; use pulldown_cmark::*; -use serde_json; -use book::{Book, BookItem}; -use config::Search; -use errors::*; -use theme::searcher; -use utils; +use crate::book::{Book, BookItem}; +use crate::config::Search; +use crate::errors::*; +use crate::theme::searcher; +use crate::utils; /// Creates all files required for search. pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> Result<()> { @@ -35,7 +31,7 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> utils::fs::write_file( destination, "searchindex.js", - format!("window.search = {};", index).as_bytes(), + format!("Object.assign(window.search, {});", index).as_bytes(), )?; utils::fs::write_file(destination, "searcher.js", searcher::JS)?; utils::fs::write_file(destination, "mark.min.js", searcher::MARK_JS)?; @@ -85,16 +81,14 @@ fn render_item( .chain_err(|| "Could not convert HTML path to str")?; let anchor_base = utils::fs::normalize_path(filepath); - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - let p = Parser::new_ext(&chapter.content, opts); + let p = utils::new_cmark_parser(&chapter.content); let mut in_header = false; - let max_section_depth = search_config.heading_split_level as i32; + let max_section_depth = i32::from(search_config.heading_split_level); let mut section_id = None; let mut heading = String::new(); let mut body = String::new(); + let mut html_block = String::new(); let mut breadcrumbs = chapter.parent_names.clone(); let mut footnote_numbers = HashMap::new(); @@ -128,6 +122,13 @@ fn render_item( let number = footnote_numbers.len() + 1; footnote_numbers.entry(name).or_insert(number); } + Event::Html(html) => { + html_block.push_str(&html); + } + Event::End(Tag::HtmlBlock) => { + body.push_str(&clean_html(&html_block)); + html_block.clear(); + } Event::Start(_) | Event::End(_) | Event::SoftBreak | Event::HardBreak => { // Insert spaces where HTML output would usually seperate text // to ensure words don't get merged together @@ -137,14 +138,14 @@ fn render_item( body.push(' '); } } - Event::Text(text) => { + Event::Text(text) | Event::Code(text) => { if in_header { heading.push_str(&text); } else { body.push_str(&text); } } - Event::Html(html) | Event::InlineHtml(html) => { + Event::InlineHtml(html) => { body.push_str(&clean_html(&html)); } Event::FootnoteReference(name) => { @@ -152,6 +153,7 @@ fn render_item( let number = footnote_numbers.entry(name).or_insert(len); body.push_str(&format!(" [{}] ", number)); } + Event::TaskListMarker(_checked) => {} } } @@ -170,7 +172,7 @@ fn render_item( } fn write_to_json(index: Index, search_config: &Search, doc_urls: Vec<String>) -> Result<String> { - use self::elasticlunr::config::{SearchBool, SearchOptions, SearchOptionsField}; + use elasticlunr::config::{SearchBool, SearchOptions, SearchOptionsField}; use std::collections::BTreeMap; #[derive(Serialize)] diff --git a/vendor/mdbook/src/renderer/mod.rs b/vendor/mdbook/src/renderer/mod.rs index ae26c6ac71..d4243332b5 100644 --- a/vendor/mdbook/src/renderer/mod.rs +++ b/vendor/mdbook/src/renderer/mod.rs @@ -15,16 +15,15 @@ pub use self::html_handlebars::HtmlHandlebars; mod html_handlebars; -use serde_json; use shlex::Shlex; use std::fs; use std::io::{self, Read}; use std::path::PathBuf; use std::process::{Command, Stdio}; -use book::Book; -use config::Config; -use errors::*; +use crate::book::Book; +use crate::config::Config; +use crate::errors::*; /// An arbitrary `mdbook` backend. /// @@ -78,7 +77,7 @@ impl RenderContext { RenderContext { book, config, - version: ::MDBOOK_VERSION.to_string(), + version: crate::MDBOOK_VERSION.to_string(), root: root.into(), destination: destination.into(), __non_exhaustive: (), diff --git a/vendor/mdbook/src/theme/ayu-highlight.css b/vendor/mdbook/src/theme/ayu-highlight.css index 786063fc4d..128e016642 100644 --- a/vendor/mdbook/src/theme/ayu-highlight.css +++ b/vendor/mdbook/src/theme/ayu-highlight.css @@ -69,3 +69,11 @@ Original by Dempfi (https://github.com/dempfi/ayu) .hljs-strong { font-weight: bold; } + +.hljs-addition { + color: #91b362; +} + +.hljs-deletion { + color: #d96c75; +} diff --git a/vendor/mdbook/src/theme/book.js b/vendor/mdbook/src/theme/book.js index 4640e8fca1..ca73ee14d0 100644 --- a/vendor/mdbook/src/theme/book.js +++ b/vendor/mdbook/src/theme/book.js @@ -101,11 +101,15 @@ function playpen_text(playpen) { } let text = playpen_text(code_block); + let classes = code_block.querySelector('code').classList; + let has_2018 = classes.contains("edition2018"); + let edition = has_2018 ? "2018" : "2015"; var params = { version: "stable", optimize: "0", - code: text + code: text, + edition: edition }; if (text.indexOf("#![feature") !== -1) { @@ -330,13 +334,11 @@ function playpen_text(playpen) { stylesheets.ayuHighlight.disabled = false; stylesheets.tomorrowNight.disabled = true; stylesheets.highlight.disabled = true; - ace_theme = "ace/theme/tomorrow_night"; } else { stylesheets.ayuHighlight.disabled = true; stylesheets.tomorrowNight.disabled = true; stylesheets.highlight.disabled = false; - ace_theme = "ace/theme/dawn"; } @@ -435,6 +437,7 @@ function playpen_text(playpen) { var sidebar = document.getElementById("sidebar"); var sidebarLinks = document.querySelectorAll('#sidebar a'); var sidebarToggleButton = document.getElementById("sidebar-toggle"); + var sidebarResizeHandle = document.getElementById("sidebar-resize-handle"); var firstContact = null; function showSidebar() { @@ -474,6 +477,23 @@ function playpen_text(playpen) { } }); + sidebarResizeHandle.addEventListener('mousedown', initResize, false); + + function initResize(e) { + window.addEventListener('mousemove', resize, false); + window.addEventListener('mouseup', stopResize, false); + html.classList.add('sidebar-resizing'); + } + function resize(e) { + document.documentElement.style.setProperty('--sidebar-width', (e.clientX - sidebar.offsetLeft) + 'px'); + } + //on mouseup remove windows functions mousemove & mouseup + function stopResize(e) { + html.classList.remove('sidebar-resizing'); + window.removeEventListener('mousemove', resize, false); + window.removeEventListener('mouseup', stopResize, false); + } + document.addEventListener('touchstart', function (e) { firstContact = { x: e.touches[0].clientX, @@ -543,7 +563,7 @@ function playpen_text(playpen) { elem.className = 'fa fa-copy tooltipped'; } - var clipboardSnippets = new Clipboard('.clip-button', { + var clipboardSnippets = new ClipboardJS('.clip-button', { text: function (trigger) { hideTooltip(trigger); let playpen = trigger.closest("pre"); diff --git a/vendor/mdbook/src/theme/css/chrome.css b/vendor/mdbook/src/theme/css/chrome.css index 0ab1686960..94f86f7907 100644 --- a/vendor/mdbook/src/theme/css/chrome.css +++ b/vendor/mdbook/src/theme/css/chrome.css @@ -78,7 +78,7 @@ html:not(.sidebar-visible) #menu-bar:not(:hover).folded > #menu-bar-sticky-conta display: flex; margin: 0 5px; } -.no-js .left-buttons { +.no-js .left-buttons { display: none; } @@ -145,7 +145,7 @@ html:not(.sidebar-visible) #menu-bar:not(:hover).folded > #menu-bar-sticky-conta display: none; } -.mobile-nav-chapters { +.mobile-nav-chapters { font-size: 2.5em; text-align: center; text-decoration: none; @@ -180,7 +180,11 @@ html:not(.sidebar-visible) #menu-bar:not(:hover).folded > #menu-bar-sticky-conta vertical-align: middle; padding: 0.1em 0.3em; border-radius: 3px; +} + +:not(pre):not(a) > .hljs { color: var(--inline-code-color); + overflow-x: initial; } a:hover > .hljs { @@ -301,8 +305,6 @@ ul#searchresults span.teaser em { top: 0; bottom: 0; width: var(--sidebar-width); - overflow-y: auto; - padding: 10px 10px; font-size: 0.875em; box-sizing: border-box; -webkit-overflow-scrolling: touch; @@ -310,12 +312,39 @@ ul#searchresults span.teaser em { background-color: var(--sidebar-bg); color: var(--sidebar-fg); } -.js .sidebar { +.sidebar-resizing { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} +.js:not(.sidebar-resizing) .sidebar { transition: transform 0.3s; /* Animation: slide away */ } .sidebar code { line-height: 2em; } +.sidebar .sidebar-scrollbox { + overflow-y: auto; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + padding: 10px 10px; +} +.sidebar .sidebar-resize-handle { + position: absolute; + cursor: col-resize; + width: 0; + right: 0; + top: 0; + bottom: 0; +} +.js .sidebar .sidebar-resize-handle { + cursor: col-resize; + width: 5px; +} .sidebar-hidden .sidebar { transform: translateX(calc(0px - var(--sidebar-width))); } @@ -345,15 +374,17 @@ ul#searchresults span.teaser em { color: var(--sidebar-non-existant); } .chapter li a { - color: var(--sidebar-fg); display: block; padding: 0; text-decoration: none; + color: var(--sidebar-fg); } -.chapter li a:hover { text-decoration: none } -.chapter li .active, -a:hover { - /* Animate color change */ + +.chapter li a:hover { + color: var(--sidebar-active); +} + +.chapter li .active { color: var(--sidebar-active); } @@ -366,7 +397,7 @@ a:hover { background-color: var(--sidebar-spacer); } -@media (-moz-touch-enabled: 1), (pointer: coarse) { +@media (-moz-touch-enabled: 1), (pointer: coarse) { .chapter li a { padding: 5px 0; } .spacer { margin: 10px 0; } } diff --git a/vendor/mdbook/src/theme/css/general.css b/vendor/mdbook/src/theme/css/general.css index aedfb332b7..57d5d7a602 100644 --- a/vendor/mdbook/src/theme/css/general.css +++ b/vendor/mdbook/src/theme/css/general.css @@ -30,14 +30,14 @@ h4, h5 { margin-top: 2em; } .header + .header h3, .header + .header h4, -.header + .header h5 { +.header + .header h5 { margin-top: 1em; } -a.header:target h1:before, -a.header:target h2:before, -a.header:target h3:before, -a.header:target h4:before { +h1 a.header:target::before, +h2 a.header:target::before, +h3 a.header:target::before, +h4 a.header:target::before { display: inline-block; content: "»"; margin-left: -30px; @@ -51,7 +51,7 @@ a.header:target h4:before { .page-wrapper { box-sizing: border-box; } -.js .page-wrapper { +.js:not(.sidebar-resizing) .page-wrapper { transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */ } @@ -141,4 +141,3 @@ blockquote { .tooltipped .tooltiptext { visibility: visible; } - \ No newline at end of file diff --git a/vendor/mdbook/src/theme/index.hbs b/vendor/mdbook/src/theme/index.hbs index bfe4283a9d..4e29807c6f 100644 --- a/vendor/mdbook/src/theme/index.hbs +++ b/vendor/mdbook/src/theme/index.hbs @@ -4,6 +4,10 @@ <!-- Book generated using mdBook --> <meta charset="UTF-8"> <title>{{ title }} + {{#if is_print }} + + {{/if}} + @@ -61,7 +65,7 @@
@@ -110,7 +117,7 @@ {{/if}}
-

{{ book_title }}

+

{{ book_title }}

-

Useless

-]]>"##; - - use pulldown_cmark::{Parser, html}; - - let mut s = String::new(); - - let p = Parser::new(&original); - html::push_html(&mut s, p); - - assert_eq!(expected, s); -} - -#[test] -fn html_test_6() { - let original = r##"Little header - -"##; - let expected = r##"

Little header

-"##; - - use pulldown_cmark::{Parser, html}; - - let mut s = String::new(); - - let p = Parser::new(&original); - html::push_html(&mut s, p); - - assert_eq!(expected, s); -} - -#[test] -fn html_test_7() { - let original = r##"Little header ------------ - -"##; - let expected = r##"

Little header

-"##; - - use pulldown_cmark::{Parser, html}; - - let mut s = String::new(); - - let p = Parser::new(&original); - html::push_html(&mut s, p); - - assert_eq!(expected, s); -} - -#[test] -fn html_test_broken_callback() { - let original = r##"[foo], -[bar], -[baz], - - [baz]: https://example.org -"##; - - let expected = r##"

foo, -[bar], -baz,

-"##; - - use pulldown_cmark::{Options, Parser, html}; - - let mut s = String::new(); - - let callback = |reference: &str, _normalized: &str| -> Option<(String, String)> { - if reference == "foo" || reference == "baz" { - Some(("https://replaced.example.org".into(), "some title".into())) - } else { - None - } - }; - - let p = Parser::new_with_broken_link_callback(&original, Options::empty(), Some(&callback)); - html::push_html(&mut s, p); - - assert_eq!(expected, s); -} diff --git a/vendor/pulldown-cmark-0.1.2/tests/spec.rs b/vendor/pulldown-cmark-0.1.2/tests/spec.rs deleted file mode 100644 index 0af21284cc..0000000000 --- a/vendor/pulldown-cmark-0.1.2/tests/spec.rs +++ /dev/null @@ -1,14997 +0,0 @@ -// This file is auto-generated by the build script -// Please, do not modify it manually - -extern crate pulldown_cmark; - - - #[test] - fn spec_test_1() { - let original = r##" foo baz bim -"##; - let expected = r##"
foo	baz		bim
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_2() { - let original = r##" foo baz bim -"##; - let expected = r##"
foo	baz		bim
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_3() { - let original = r##" a a - ὐ a -"##; - let expected = r##"
a	a
-ὐ	a
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_4() { - let original = r##" - foo - - bar -"##; - let expected = r##"
    -
  • -

    foo

    -

    bar

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_5() { - let original = r##"- foo - - bar -"##; - let expected = r##"
    -
  • -

    foo

    -
      bar
    -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_6() { - let original = r##"> foo -"##; - let expected = r##"
-
  foo
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_7() { - let original = r##"- foo -"##; - let expected = r##"
    -
  • -
      foo
    -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_8() { - let original = r##" foo - bar -"##; - let expected = r##"
foo
-bar
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_9() { - let original = r##" - foo - - bar - - baz -"##; - let expected = r##"
    -
  • foo -
      -
    • bar -
        -
      • baz
      • -
      -
    • -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_10() { - let original = r##"# Foo -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_11() { - let original = r##"* * * -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_12() { - let original = r##"- `one -- two` -"##; - let expected = r##"
    -
  • `one
  • -
  • two`
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_13() { - let original = r##"*** ---- -___ -"##; - let expected = r##"
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_14() { - let original = r##"+++ -"##; - let expected = r##"

+++

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_15() { - let original = r##"=== -"##; - let expected = r##"

===

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_16() { - let original = r##"-- -** -__ -"##; - let expected = r##"

-- -** -__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_17() { - let original = r##" *** - *** - *** -"##; - let expected = r##"
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_18() { - let original = r##" *** -"##; - let expected = r##"
***
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_19() { - let original = r##"Foo - *** -"##; - let expected = r##"

Foo -***

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_20() { - let original = r##"_____________________________________ -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_21() { - let original = r##" - - - -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_22() { - let original = r##" ** * ** * ** * ** -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_23() { - let original = r##"- - - - -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_24() { - let original = r##"- - - - -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_25() { - let original = r##"_ _ _ _ a - -a------ - ----a--- -"##; - let expected = r##"

_ _ _ _ a

-

a------

-

---a---

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_26() { - let original = r##" *-* -"##; - let expected = r##"

-

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_27() { - let original = r##"- foo -*** -- bar -"##; - let expected = r##"
    -
  • foo
  • -
-
-
    -
  • bar
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_28() { - let original = r##"Foo -*** -bar -"##; - let expected = r##"

Foo

-
-

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_29() { - let original = r##"Foo ---- -bar -"##; - let expected = r##"

Foo

-

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_30() { - let original = r##"* Foo -* * * -* Bar -"##; - let expected = r##"
    -
  • Foo
  • -
-
-
    -
  • Bar
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_31() { - let original = r##"- Foo -- * * * -"##; - let expected = r##"
    -
  • Foo
  • -
  • -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_32() { - let original = r##"# foo -## foo -### foo -#### foo -##### foo -###### foo -"##; - let expected = r##"

foo

-

foo

-

foo

-

foo

-
foo
-
foo
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_33() { - let original = r##"####### foo -"##; - let expected = r##"

####### foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_34() { - let original = r##"#5 bolt - -#hashtag -"##; - let expected = r##"

#5 bolt

-

#hashtag

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_35() { - let original = r##"\## foo -"##; - let expected = r##"

## foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_36() { - let original = r##"# foo *bar* \*baz\* -"##; - let expected = r##"

foo bar *baz*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_37() { - let original = r##"# foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_38() { - let original = r##" ### foo - ## foo - # foo -"##; - let expected = r##"

foo

-

foo

-

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_39() { - let original = r##" # foo -"##; - let expected = r##"
# foo
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_40() { - let original = r##"foo - # bar -"##; - let expected = r##"

foo -# bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_41() { - let original = r##"## foo ## - ### bar ### -"##; - let expected = r##"

foo

-

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_42() { - let original = r##"# foo ################################## -##### foo ## -"##; - let expected = r##"

foo

-
foo
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_43() { - let original = r##"### foo ### -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_44() { - let original = r##"### foo ### b -"##; - let expected = r##"

foo ### b

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_45() { - let original = r##"# foo# -"##; - let expected = r##"

foo#

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_46() { - let original = r##"### foo \### -## foo #\## -# foo \# -"##; - let expected = r##"

foo ###

-

foo ###

-

foo #

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_47() { - let original = r##"**** -## foo -**** -"##; - let expected = r##"
-

foo

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_48() { - let original = r##"Foo bar -# baz -Bar foo -"##; - let expected = r##"

Foo bar

-

baz

-

Bar foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_49() { - let original = r##"## -# -### ### -"##; - let expected = r##"

-

-

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_50() { - let original = r##"Foo *bar* -========= - -Foo *bar* ---------- -"##; - let expected = r##"

Foo bar

-

Foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_51() { - let original = r##"Foo *bar -baz* -==== -"##; - let expected = r##"

Foo bar -baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_52() { - let original = r##"Foo -------------------------- - -Foo -= -"##; - let expected = r##"

Foo

-

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_53() { - let original = r##" Foo ---- - - Foo ------ - - Foo - === -"##; - let expected = r##"

Foo

-

Foo

-

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_54() { - let original = r##" Foo - --- - - Foo ---- -"##; - let expected = r##"
Foo
----
-
-Foo
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_55() { - let original = r##"Foo - ---- -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_56() { - let original = r##"Foo - --- -"##; - let expected = r##"

Foo ----

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_57() { - let original = r##"Foo -= = - -Foo ---- - -"##; - let expected = r##"

Foo -= =

-

Foo

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_58() { - let original = r##"Foo ------ -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_59() { - let original = r##"Foo\ ----- -"##; - let expected = r##"

Foo\

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_60() { - let original = r##"`Foo ----- -` - - -"##; - let expected = r##"

`Foo

-

`

-

<a title="a lot

-

of dashes"/>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_61() { - let original = r##"> Foo ---- -"##; - let expected = r##"
-

Foo

-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_62() { - let original = r##"> foo -bar -=== -"##; - let expected = r##"
-

foo -bar -===

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_63() { - let original = r##"- Foo ---- -"##; - let expected = r##"
    -
  • Foo
  • -
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_64() { - let original = r##"Foo -Bar ---- -"##; - let expected = r##"

Foo -Bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_65() { - let original = r##"--- -Foo ---- -Bar ---- -Baz -"##; - let expected = r##"
-

Foo

-

Bar

-

Baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_66() { - let original = r##" -==== -"##; - let expected = r##"

====

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_67() { - let original = r##"--- ---- -"##; - let expected = r##"
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_68() { - let original = r##"- foo ------ -"##; - let expected = r##"
    -
  • foo
  • -
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_69() { - let original = r##" foo ---- -"##; - let expected = r##"
foo
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_70() { - let original = r##"> foo ------ -"##; - let expected = r##"
-

foo

-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_71() { - let original = r##"\> foo ------- -"##; - let expected = r##"

> foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_72() { - let original = r##"Foo - -bar ---- -baz -"##; - let expected = r##"

Foo

-

bar

-

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_73() { - let original = r##"Foo -bar - ---- - -baz -"##; - let expected = r##"

Foo -bar

-
-

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_74() { - let original = r##"Foo -bar -* * * -baz -"##; - let expected = r##"

Foo -bar

-
-

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_75() { - let original = r##"Foo -bar -\--- -baz -"##; - let expected = r##"

Foo -bar ---- -baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_76() { - let original = r##" a simple - indented code block -"##; - let expected = r##"
a simple
-  indented code block
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_77() { - let original = r##" - foo - - bar -"##; - let expected = r##"
    -
  • -

    foo

    -

    bar

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_78() { - let original = r##"1. foo - - - bar -"##; - let expected = r##"
    -
  1. -

    foo

    -
      -
    • bar
    • -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_79() { - let original = r##"
- *hi* - - - one -"##; - let expected = r##"
<a/>
-*hi*
-
-- one
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_80() { - let original = r##" chunk1 - - chunk2 - - - - chunk3 -"##; - let expected = r##"
chunk1
-
-chunk2
-
-
-
-chunk3
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_81() { - let original = r##" chunk1 - - chunk2 -"##; - let expected = r##"
chunk1
-  
-  chunk2
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_82() { - let original = r##"Foo - bar - -"##; - let expected = r##"

Foo -bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_83() { - let original = r##" foo -bar -"##; - let expected = r##"
foo
-
-

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_84() { - let original = r##"# Heading - foo -Heading ------- - foo ----- -"##; - let expected = r##"

Heading

-
foo
-
-

Heading

-
foo
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_85() { - let original = r##" foo - bar -"##; - let expected = r##"
    foo
-bar
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_86() { - let original = r##" - - foo - - -"##; - let expected = r##"
foo
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_87() { - let original = r##" foo -"##; - let expected = r##"
foo  
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_88() { - let original = r##"``` -< - > -``` -"##; - let expected = r##"
<
- >
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_89() { - let original = r##"~~~ -< - > -~~~ -"##; - let expected = r##"
<
- >
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_90() { - let original = r##"`` -foo -`` -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_91() { - let original = r##"``` -aaa -~~~ -``` -"##; - let expected = r##"
aaa
-~~~
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_92() { - let original = r##"~~~ -aaa -``` -~~~ -"##; - let expected = r##"
aaa
-```
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_93() { - let original = r##"```` -aaa -``` -`````` -"##; - let expected = r##"
aaa
-```
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_94() { - let original = r##"~~~~ -aaa -~~~ -~~~~ -"##; - let expected = r##"
aaa
-~~~
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_95() { - let original = r##"``` -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_96() { - let original = r##"````` - -``` -aaa -"##; - let expected = r##"

-```
-aaa
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_97() { - let original = r##"> ``` -> aaa - -bbb -"##; - let expected = r##"
-
aaa
-
-
-

bbb

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_98() { - let original = r##"``` - - -``` -"##; - let expected = r##"

-  
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_99() { - let original = r##"``` -``` -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_100() { - let original = r##" ``` - aaa -aaa -``` -"##; - let expected = r##"
aaa
-aaa
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_101() { - let original = r##" ``` -aaa - aaa -aaa - ``` -"##; - let expected = r##"
aaa
-aaa
-aaa
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_102() { - let original = r##" ``` - aaa - aaa - aaa - ``` -"##; - let expected = r##"
aaa
- aaa
-aaa
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_103() { - let original = r##" ``` - aaa - ``` -"##; - let expected = r##"
```
-aaa
-```
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_104() { - let original = r##"``` -aaa - ``` -"##; - let expected = r##"
aaa
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_105() { - let original = r##" ``` -aaa - ``` -"##; - let expected = r##"
aaa
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_106() { - let original = r##"``` -aaa - ``` -"##; - let expected = r##"
aaa
-    ```
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_107() { - let original = r##"``` ``` -aaa -"##; - let expected = r##"

-aaa

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_108() { - let original = r##"~~~~~~ -aaa -~~~ ~~ -"##; - let expected = r##"
aaa
-~~~ ~~
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_109() { - let original = r##"foo -``` -bar -``` -baz -"##; - let expected = r##"

foo

-
bar
-
-

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_110() { - let original = r##"foo ---- -~~~ -bar -~~~ -# baz -"##; - let expected = r##"

foo

-
bar
-
-

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_111() { - let original = r##"```ruby -def foo(x) - return 3 -end -``` -"##; - let expected = r##"
def foo(x)
-  return 3
-end
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_112() { - let original = r##"~~~~ ruby startline=3 $%@#$ -def foo(x) - return 3 -end -~~~~~~~ -"##; - let expected = r##"
def foo(x)
-  return 3
-end
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_113() { - let original = r##"````; -```` -"##; - let expected = r##"
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_114() { - let original = r##"``` aa ``` -foo -"##; - let expected = r##"

aa -foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_115() { - let original = r##"``` -``` aaa -``` -"##; - let expected = r##"
``` aaa
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_116() { - let original = r##"
-
-**Hello**,
-
-_world_.
-
-
-"##; - let expected = r##"
-
-**Hello**,
-

world. -

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_117() { - let original = r##" - - - -
- hi -
- -okay. -"##; - let expected = r##" - - - -
- hi -
-

okay.

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_118() { - let original = r##"
-*foo* -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_120() { - let original = r##"
- -*Markdown* - -
-"##; - let expected = r##"
-

Markdown

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_121() { - let original = r##"
-
-"##; - let expected = r##"
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_122() { - let original = r##"
-
-"##; - let expected = r##"
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_123() { - let original = r##"
-*foo* - -*bar* -"##; - let expected = r##"
-*foo* -

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_124() { - let original = r##"
-"##; - let expected = r##" -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_128() { - let original = r##"
-foo -
-"##; - let expected = r##"
-foo -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_129() { - let original = r##"
-``` c -int x = 33; -``` -"##; - let expected = r##"
-``` c -int x = 33; -``` -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_130() { - let original = r##" -*bar* - -"##; - let expected = r##" -*bar* - -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_131() { - let original = r##" -*bar* - -"##; - let expected = r##" -*bar* - -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_132() { - let original = r##" -*bar* - -"##; - let expected = r##" -*bar* - -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_133() { - let original = r##" -*bar* -"##; - let expected = r##" -*bar* -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_134() { - let original = r##" -*foo* - -"##; - let expected = r##" -*foo* - -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_135() { - let original = r##" - -*foo* - - -"##; - let expected = r##" -

foo

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_136() { - let original = r##"*foo* -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_137() { - let original = r##"

-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-
-okay -"##; - let expected = r##"

-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-
-

okay

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_138() { - let original = r##" -okay -"##; - let expected = r##" -

okay

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_139() { - let original = r##" -okay -"##; - let expected = r##" -

okay

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_140() { - let original = r##" -*foo* -"##; - let expected = r##" -

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_144() { - let original = r##"*bar* -*baz* -"##; - let expected = r##"*bar* -

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_145() { - let original = r##"1. *bar* -"##; - let expected = r##"1. *bar* -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_146() { - let original = r##" -okay -"##; - let expected = r##" -

okay

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_147() { - let original = r##"'; - -?> -okay -"##; - let expected = r##"'; - -?> -

okay

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_148() { - let original = r##" -"##; - let expected = r##" -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_149() { - let original = r##" -okay -"##; - let expected = r##" -

okay

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_150() { - let original = r##" - - -"##; - let expected = r##" -
<!-- foo -->
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_151() { - let original = r##"
- -
-"##; - let expected = r##"
-
<div>
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_152() { - let original = r##"Foo -
-bar -
-"##; - let expected = r##"

Foo

-
-bar -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_153() { - let original = r##"
-bar -
-*foo* -"##; - let expected = r##"
-bar -
-*foo* -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_154() { - let original = r##"Foo - -baz -"##; - let expected = r##"

Foo - -baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_155() { - let original = r##"
- -*Emphasized* text. - -
-"##; - let expected = r##"
-

Emphasized text.

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_156() { - let original = r##"
-*Emphasized* text. -
-"##; - let expected = r##"
-*Emphasized* text. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_157() { - let original = r##" - - - - - - - -
-Hi -
-"##; - let expected = r##" - - - -
-Hi -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_158() { - let original = r##" - - - - - - - -
- Hi -
-"##; - let expected = r##" - -
<td>
-  Hi
-</td>
-
- -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_159() { - let original = r##"[foo]: /url "title" - -[foo] -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_160() { - let original = r##" [foo]: - /url - 'the title' - -[foo] -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_161() { - let original = r##"[Foo*bar\]]:my_(url) 'title (with parens)' - -[Foo*bar\]] -"##; - let expected = r##"

Foo*bar]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_162() { - let original = r##"[Foo bar]: - -'title' - -[Foo bar] -"##; - let expected = r##"

Foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_163() { - let original = r##"[foo]: /url ' -title -line1 -line2 -' - -[foo] -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_164() { - let original = r##"[foo]: /url 'title - -with blank line' - -[foo] -"##; - let expected = r##"

[foo]: /url 'title

-

with blank line'

-

[foo]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_165() { - let original = r##"[foo]: -/url - -[foo] -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_166() { - let original = r##"[foo]: - -[foo] -"##; - let expected = r##"

[foo]:

-

[foo]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_167() { - let original = r##"[foo]: /url\bar\*baz "foo\"bar\baz" - -[foo] -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_168() { - let original = r##"[foo] - -[foo]: url -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_169() { - let original = r##"[foo] - -[foo]: first -[foo]: second -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_170() { - let original = r##"[FOO]: /url - -[Foo] -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_171() { - let original = r##"[ΑΓΩ]: /φου - -[αγω] -"##; - let expected = r##"

αγω

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_172() { - let original = r##"[foo]: /url -"##; - let expected = r##""##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_173() { - let original = r##"[ -foo -]: /url -bar -"##; - let expected = r##"

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_174() { - let original = r##"[foo]: /url "title" ok -"##; - let expected = r##"

[foo]: /url "title" ok

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_175() { - let original = r##"[foo]: /url -"title" ok -"##; - let expected = r##"

"title" ok

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_176() { - let original = r##" [foo]: /url "title" - -[foo] -"##; - let expected = r##"
[foo]: /url "title"
-
-

[foo]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_177() { - let original = r##"``` -[foo]: /url -``` - -[foo] -"##; - let expected = r##"
[foo]: /url
-
-

[foo]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_178() { - let original = r##"Foo -[bar]: /baz - -[bar] -"##; - let expected = r##"

Foo -[bar]: /baz

-

[bar]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_179() { - let original = r##"# [Foo] -[foo]: /url -> bar -"##; - let expected = r##"

Foo

-
-

bar

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_180() { - let original = r##"[foo]: /foo-url "foo" -[bar]: /bar-url - "bar" -[baz]: /baz-url - -[foo], -[bar], -[baz] -"##; - let expected = r##"

foo, -bar, -baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_181() { - let original = r##"[foo] - -> [foo]: /url -"##; - let expected = r##"

foo

-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_182() { - let original = r##"aaa - -bbb -"##; - let expected = r##"

aaa

-

bbb

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_183() { - let original = r##"aaa -bbb - -ccc -ddd -"##; - let expected = r##"

aaa -bbb

-

ccc -ddd

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_184() { - let original = r##"aaa - - -bbb -"##; - let expected = r##"

aaa

-

bbb

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_185() { - let original = r##" aaa - bbb -"##; - let expected = r##"

aaa -bbb

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_186() { - let original = r##"aaa - bbb - ccc -"##; - let expected = r##"

aaa -bbb -ccc

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_187() { - let original = r##" aaa -bbb -"##; - let expected = r##"

aaa -bbb

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_188() { - let original = r##" aaa -bbb -"##; - let expected = r##"
aaa
-
-

bbb

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_189() { - let original = r##"aaa -bbb -"##; - let expected = r##"

aaa
-bbb

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_190() { - let original = r##" - -aaa - - -# aaa - - -"##; - let expected = r##"

aaa

-

aaa

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_191() { - let original = r##"> # Foo -> bar -> baz -"##; - let expected = r##"
-

Foo

-

bar -baz

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_192() { - let original = r##"># Foo ->bar -> baz -"##; - let expected = r##"
-

Foo

-

bar -baz

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_193() { - let original = r##" > # Foo - > bar - > baz -"##; - let expected = r##"
-

Foo

-

bar -baz

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_194() { - let original = r##" > # Foo - > bar - > baz -"##; - let expected = r##"
> # Foo
-> bar
-> baz
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_195() { - let original = r##"> # Foo -> bar -baz -"##; - let expected = r##"
-

Foo

-

bar -baz

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_196() { - let original = r##"> bar -baz -> foo -"##; - let expected = r##"
-

bar -baz -foo

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_197() { - let original = r##"> foo ---- -"##; - let expected = r##"
-

foo

-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_198() { - let original = r##"> - foo -- bar -"##; - let expected = r##"
-
    -
  • foo
  • -
-
-
    -
  • bar
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_199() { - let original = r##"> foo - bar -"##; - let expected = r##"
-
foo
-
-
-
bar
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_200() { - let original = r##"> ``` -foo -``` -"##; - let expected = r##"
-
-
-

foo

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_201() { - let original = r##"> foo - - bar -"##; - let expected = r##"
-

foo -- bar

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_202() { - let original = r##"> -"##; - let expected = r##"
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_203() { - let original = r##"> -> -> -"##; - let expected = r##"
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_204() { - let original = r##"> -> foo -> -"##; - let expected = r##"
-

foo

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_205() { - let original = r##"> foo - -> bar -"##; - let expected = r##"
-

foo

-
-
-

bar

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_206() { - let original = r##"> foo -> bar -"##; - let expected = r##"
-

foo -bar

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_207() { - let original = r##"> foo -> -> bar -"##; - let expected = r##"
-

foo

-

bar

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_208() { - let original = r##"foo -> bar -"##; - let expected = r##"

foo

-
-

bar

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_209() { - let original = r##"> aaa -*** -> bbb -"##; - let expected = r##"
-

aaa

-
-
-
-

bbb

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_210() { - let original = r##"> bar -baz -"##; - let expected = r##"
-

bar -baz

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_211() { - let original = r##"> bar - -baz -"##; - let expected = r##"
-

bar

-
-

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_212() { - let original = r##"> bar -> -baz -"##; - let expected = r##"
-

bar

-
-

baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_213() { - let original = r##"> > > foo -bar -"##; - let expected = r##"
-
-
-

foo -bar

-
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_214() { - let original = r##">>> foo -> bar ->>baz -"##; - let expected = r##"
-
-
-

foo -bar -baz

-
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_215() { - let original = r##"> code - -> not code -"##; - let expected = r##"
-
code
-
-
-
-

not code

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_216() { - let original = r##"A paragraph -with two lines. - - indented code - -> A block quote. -"##; - let expected = r##"

A paragraph -with two lines.

-
indented code
-
-
-

A block quote.

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_217() { - let original = r##"1. A paragraph - with two lines. - - indented code - - > A block quote. -"##; - let expected = r##"
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_218() { - let original = r##"- one - - two -"##; - let expected = r##"
    -
  • one
  • -
-

two

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_219() { - let original = r##"- one - - two -"##; - let expected = r##"
    -
  • -

    one

    -

    two

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_220() { - let original = r##" - one - - two -"##; - let expected = r##"
    -
  • one
  • -
-
 two
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_221() { - let original = r##" - one - - two -"##; - let expected = r##"
    -
  • -

    one

    -

    two

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_222() { - let original = r##" > > 1. one ->> ->> two -"##; - let expected = r##"
-
-
    -
  1. -

    one

    -

    two

    -
  2. -
-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_223() { - let original = r##">>- one ->> - > > two -"##; - let expected = r##"
-
-
    -
  • one
  • -
-

two

-
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_224() { - let original = r##"-one - -2.two -"##; - let expected = r##"

-one

-

2.two

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_225() { - let original = r##"- foo - - - bar -"##; - let expected = r##"
    -
  • -

    foo

    -

    bar

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_226() { - let original = r##"1. foo - - ``` - bar - ``` - - baz - - > bam -"##; - let expected = r##"
    -
  1. -

    foo

    -
    bar
    -
    -

    baz

    -
    -

    bam

    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_227() { - let original = r##"- Foo - - bar - - - baz -"##; - let expected = r##"
    -
  • -

    Foo

    -
    bar
    -
    -
    -baz
    -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_228() { - let original = r##"123456789. ok -"##; - let expected = r##"
    -
  1. ok
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_229() { - let original = r##"1234567890. not ok -"##; - let expected = r##"

1234567890. not ok

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_230() { - let original = r##"0. ok -"##; - let expected = r##"
    -
  1. ok
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_231() { - let original = r##"003. ok -"##; - let expected = r##"
    -
  1. ok
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_232() { - let original = r##"-1. not ok -"##; - let expected = r##"

-1. not ok

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_233() { - let original = r##"- foo - - bar -"##; - let expected = r##"
    -
  • -

    foo

    -
    bar
    -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_234() { - let original = r##" 10. foo - - bar -"##; - let expected = r##"
    -
  1. -

    foo

    -
    bar
    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_235() { - let original = r##" indented code - -paragraph - - more code -"##; - let expected = r##"
indented code
-
-

paragraph

-
more code
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_236() { - let original = r##"1. indented code - - paragraph - - more code -"##; - let expected = r##"
    -
  1. -
    indented code
    -
    -

    paragraph

    -
    more code
    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_237() { - let original = r##"1. indented code - - paragraph - - more code -"##; - let expected = r##"
    -
  1. -
     indented code
    -
    -

    paragraph

    -
    more code
    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_238() { - let original = r##" foo - -bar -"##; - let expected = r##"

foo

-

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_239() { - let original = r##"- foo - - bar -"##; - let expected = r##"
    -
  • foo
  • -
-

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_240() { - let original = r##"- foo - - bar -"##; - let expected = r##"
    -
  • -

    foo

    -

    bar

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_241() { - let original = r##"- - foo -- - ``` - bar - ``` -- - baz -"##; - let expected = r##"
    -
  • foo
  • -
  • -
    bar
    -
    -
  • -
  • -
    baz
    -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_242() { - let original = r##"- - foo -"##; - let expected = r##"
    -
  • foo
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_243() { - let original = r##"- - - foo -"##; - let expected = r##"
    -
  • -
-

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_244() { - let original = r##"- foo -- -- bar -"##; - let expected = r##"
    -
  • foo
  • -
  • -
  • bar
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_245() { - let original = r##"- foo -- -- bar -"##; - let expected = r##"
    -
  • foo
  • -
  • -
  • bar
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_246() { - let original = r##"1. foo -2. -3. bar -"##; - let expected = r##"
    -
  1. foo
  2. -
  3. -
  4. bar
  5. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_247() { - let original = r##"* -"##; - let expected = r##"
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_248() { - let original = r##"foo -* - -foo -1. -"##; - let expected = r##"

foo -*

-

foo -1.

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_249() { - let original = r##" 1. A paragraph - with two lines. - - indented code - - > A block quote. -"##; - let expected = r##"
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_250() { - let original = r##" 1. A paragraph - with two lines. - - indented code - - > A block quote. -"##; - let expected = r##"
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_251() { - let original = r##" 1. A paragraph - with two lines. - - indented code - - > A block quote. -"##; - let expected = r##"
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_252() { - let original = r##" 1. A paragraph - with two lines. - - indented code - - > A block quote. -"##; - let expected = r##"
1.  A paragraph
-    with two lines.
-
-        indented code
-
-    > A block quote.
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_253() { - let original = r##" 1. A paragraph -with two lines. - - indented code - - > A block quote. -"##; - let expected = r##"
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_254() { - let original = r##" 1. A paragraph - with two lines. -"##; - let expected = r##"
    -
  1. A paragraph -with two lines.
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_255() { - let original = r##"> 1. > Blockquote -continued here. -"##; - let expected = r##"
-
    -
  1. -
    -

    Blockquote -continued here.

    -
    -
  2. -
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_256() { - let original = r##"> 1. > Blockquote -> continued here. -"##; - let expected = r##"
-
    -
  1. -
    -

    Blockquote -continued here.

    -
    -
  2. -
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_257() { - let original = r##"- foo - - bar - - baz - - boo -"##; - let expected = r##"
    -
  • foo -
      -
    • bar -
        -
      • baz -
          -
        • boo
        • -
        -
      • -
      -
    • -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_258() { - let original = r##"- foo - - bar - - baz - - boo -"##; - let expected = r##"
    -
  • foo
  • -
  • bar
  • -
  • baz
  • -
  • boo
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_259() { - let original = r##"10) foo - - bar -"##; - let expected = r##"
    -
  1. foo -
      -
    • bar
    • -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_260() { - let original = r##"10) foo - - bar -"##; - let expected = r##"
    -
  1. foo
  2. -
-
    -
  • bar
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_261() { - let original = r##"- - foo -"##; - let expected = r##"
    -
  • -
      -
    • foo
    • -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_262() { - let original = r##"1. - 2. foo -"##; - let expected = r##"
    -
  1. -
      -
    • -
        -
      1. foo
      2. -
      -
    • -
    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_263() { - let original = r##"- # Foo -- Bar - --- - baz -"##; - let expected = r##"
    -
  • -

    Foo

    -
  • -
  • -

    Bar

    -baz
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_264() { - let original = r##"- foo -- bar -+ baz -"##; - let expected = r##"
    -
  • foo
  • -
  • bar
  • -
-
    -
  • baz
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_265() { - let original = r##"1. foo -2. bar -3) baz -"##; - let expected = r##"
    -
  1. foo
  2. -
  3. bar
  4. -
-
    -
  1. baz
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_266() { - let original = r##"Foo -- bar -- baz -"##; - let expected = r##"

Foo

-
    -
  • bar
  • -
  • baz
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_267() { - let original = r##"The number of windows in my house is -14. The number of doors is 6. -"##; - let expected = r##"

The number of windows in my house is -14. The number of doors is 6.

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_268() { - let original = r##"The number of windows in my house is -1. The number of doors is 6. -"##; - let expected = r##"

The number of windows in my house is

-
    -
  1. The number of doors is 6.
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_269() { - let original = r##"- foo - -- bar - - -- baz -"##; - let expected = r##"
    -
  • -

    foo

    -
  • -
  • -

    bar

    -
  • -
  • -

    baz

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_270() { - let original = r##"- foo - - bar - - baz - - - bim -"##; - let expected = r##"
    -
  • foo -
      -
    • bar -
        -
      • -

        baz

        -

        bim

        -
      • -
      -
    • -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_271() { - let original = r##"- foo -- bar - - - -- baz -- bim -"##; - let expected = r##"
    -
  • foo
  • -
  • bar
  • -
- -
    -
  • baz
  • -
  • bim
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_272() { - let original = r##"- foo - - notcode - -- foo - - - - code -"##; - let expected = r##"
    -
  • -

    foo

    -

    notcode

    -
  • -
  • -

    foo

    -
  • -
- -
code
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_273() { - let original = r##"- a - - b - - c - - d - - e - - f - - g - - h -- i -"##; - let expected = r##"
    -
  • a
  • -
  • b
  • -
  • c
  • -
  • d
  • -
  • e
  • -
  • f
  • -
  • g
  • -
  • h
  • -
  • i
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_274() { - let original = r##"1. a - - 2. b - - 3. c -"##; - let expected = r##"
    -
  1. -

    a

    -
  2. -
  3. -

    b

    -
  4. -
  5. -

    c

    -
  6. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_275() { - let original = r##"- a -- b - -- c -"##; - let expected = r##"
    -
  • -

    a

    -
  • -
  • -

    b

    -
  • -
  • -

    c

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_276() { - let original = r##"* a -* - -* c -"##; - let expected = r##"
    -
  • -

    a

    -
  • -
  • -
  • -

    c

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_277() { - let original = r##"- a -- b - - c -- d -"##; - let expected = r##"
    -
  • -

    a

    -
  • -
  • -

    b

    -

    c

    -
  • -
  • -

    d

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_278() { - let original = r##"- a -- b - - [ref]: /url -- d -"##; - let expected = r##"
    -
  • -

    a

    -
  • -
  • -

    b

    -
  • -
  • -

    d

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_279() { - let original = r##"- a -- ``` - b - - - ``` -- c -"##; - let expected = r##"
    -
  • a
  • -
  • -
    b
    -
    -
    -
    -
  • -
  • c
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_280() { - let original = r##"- a - - b - - c -- d -"##; - let expected = r##"
    -
  • a -
      -
    • -

      b

      -

      c

      -
    • -
    -
  • -
  • d
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_281() { - let original = r##"* a - > b - > -* c -"##; - let expected = r##"
    -
  • a -
    -

    b

    -
    -
  • -
  • c
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_282() { - let original = r##"- a - > b - ``` - c - ``` -- d -"##; - let expected = r##"
    -
  • a -
    -

    b

    -
    -
    c
    -
    -
  • -
  • d
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_283() { - let original = r##"- a -"##; - let expected = r##"
    -
  • a
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_284() { - let original = r##"- a - - b -"##; - let expected = r##"
    -
  • a -
      -
    • b
    • -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_285() { - let original = r##"1. ``` - foo - ``` - - bar -"##; - let expected = r##"
    -
  1. -
    foo
    -
    -

    bar

    -
  2. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_286() { - let original = r##"* foo - * bar - - baz -"##; - let expected = r##"
    -
  • -

    foo

    -
      -
    • bar
    • -
    -

    baz

    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_287() { - let original = r##"- a - - b - - c - -- d - - e - - f -"##; - let expected = r##"
    -
  • -

    a

    -
      -
    • b
    • -
    • c
    • -
    -
  • -
  • -

    d

    -
      -
    • e
    • -
    • f
    • -
    -
  • -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_288() { - let original = r##"`hi`lo` -"##; - let expected = r##"

hilo`

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_289() { - let original = r##"\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~ -"##; - let expected = r##"

!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_290() { - let original = r##"\ \A\a\ \3\φ\« -"##; - let expected = r##"

\ \A\a\ \3\φ\«

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_291() { - let original = r##"\*not emphasized* -\
not a tag -\[not a link](/foo) -\`not code` -1\. not a list -\* not a list -\# not a heading -\[foo]: /url "not a reference" -"##; - let expected = r##"

*not emphasized* -<br/> not a tag -[not a link](/foo) -`not code` -1. not a list -* not a list -# not a heading -[foo]: /url "not a reference"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_292() { - let original = r##"\\*emphasis* -"##; - let expected = r##"

\emphasis

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_293() { - let original = r##"foo\ -bar -"##; - let expected = r##"

foo
-bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_294() { - let original = r##"`` \[\` `` -"##; - let expected = r##"

\[\`

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_295() { - let original = r##" \[\] -"##; - let expected = r##"
\[\]
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_296() { - let original = r##"~~~ -\[\] -~~~ -"##; - let expected = r##"
\[\]
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_297() { - let original = r##" -"##; - let expected = r##"

http://example.com?find=\*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_298() { - let original = r##" -"##; - let expected = r##" -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_299() { - let original = r##"[foo](/bar\* "ti\*tle") -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_300() { - let original = r##"[foo] - -[foo]: /bar\* "ti\*tle" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_301() { - let original = r##"``` foo\+bar -foo -``` -"##; - let expected = r##"
foo
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_302() { - let original = r##"  & © Æ Ď -¾ ℋ ⅆ -∲ ≧̸ -"##; - let expected = r##"

  & © Æ Ď -¾ ℋ ⅆ -∲ ≧̸

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_303() { - let original = r##"# Ӓ Ϡ � � -"##; - let expected = r##"

# Ӓ Ϡ � �

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_304() { - let original = r##"" ആ ಫ -"##; - let expected = r##"

" ആ ಫ

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_305() { - let original = r##"  &x; &#; &#x; -&ThisIsNotDefined; &hi?; -"##; - let expected = r##"

&nbsp &x; &#; &#x; -&ThisIsNotDefined; &hi?;

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_306() { - let original = r##"© -"##; - let expected = r##"

&copy

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_307() { - let original = r##"&MadeUpEntity; -"##; - let expected = r##"

&MadeUpEntity;

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_308() { - let original = r##" -"##; - let expected = r##" -"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_309() { - let original = r##"[foo](/föö "föö") -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_310() { - let original = r##"[foo] - -[foo]: /föö "föö" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_311() { - let original = r##"``` föö -foo -``` -"##; - let expected = r##"
foo
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_312() { - let original = r##"`föö` -"##; - let expected = r##"

f&ouml;&ouml;

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_313() { - let original = r##" föfö -"##; - let expected = r##"
f&ouml;f&ouml;
-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_314() { - let original = r##"`foo` -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_315() { - let original = r##"`` foo ` bar `` -"##; - let expected = r##"

foo ` bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_316() { - let original = r##"` `` ` -"##; - let expected = r##"

``

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_317() { - let original = r##"`` -foo -`` -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_318() { - let original = r##"`foo bar - baz` -"##; - let expected = r##"

foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_319() { - let original = r##"`a  b` -"##; - let expected = r##"

a  b

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_320() { - let original = r##"`foo `` bar` -"##; - let expected = r##"

foo `` bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_321() { - let original = r##"`foo\`bar` -"##; - let expected = r##"

foo\bar`

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_322() { - let original = r##"*foo`*` -"##; - let expected = r##"

*foo*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_323() { - let original = r##"[not a `link](/foo`) -"##; - let expected = r##"

[not a link](/foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_324() { - let original = r##"`` -"##; - let expected = r##"

<a href="">`

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_325() { - let original = r##"
` -"##; - let expected = r##"

`

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_326() { - let original = r##"`` -"##; - let expected = r##"

<http://foo.bar.baz>`

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_327() { - let original = r##"` -"##; - let expected = r##"

http://foo.bar.`baz`

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_328() { - let original = r##"```foo`` -"##; - let expected = r##"

```foo``

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_329() { - let original = r##"`foo -"##; - let expected = r##"

`foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_330() { - let original = r##"`foo``bar`` -"##; - let expected = r##"

`foobar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_331() { - let original = r##"*foo bar* -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_332() { - let original = r##"a * foo bar* -"##; - let expected = r##"

a * foo bar*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_333() { - let original = r##"a*"foo"* -"##; - let expected = r##"

a*"foo"*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_334() { - let original = r##"* a * -"##; - let expected = r##"

* a *

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_335() { - let original = r##"foo*bar* -"##; - let expected = r##"

foobar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_336() { - let original = r##"5*6*78 -"##; - let expected = r##"

5678

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_337() { - let original = r##"_foo bar_ -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_338() { - let original = r##"_ foo bar_ -"##; - let expected = r##"

_ foo bar_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_339() { - let original = r##"a_"foo"_ -"##; - let expected = r##"

a_"foo"_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_340() { - let original = r##"foo_bar_ -"##; - let expected = r##"

foo_bar_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_341() { - let original = r##"5_6_78 -"##; - let expected = r##"

5_6_78

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_342() { - let original = r##"пристаням_стремятся_ -"##; - let expected = r##"

пристаням_стремятся_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_343() { - let original = r##"aa_"bb"_cc -"##; - let expected = r##"

aa_"bb"_cc

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_344() { - let original = r##"foo-_(bar)_ -"##; - let expected = r##"

foo-(bar)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_345() { - let original = r##"_foo* -"##; - let expected = r##"

_foo*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_346() { - let original = r##"*foo bar * -"##; - let expected = r##"

*foo bar *

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_347() { - let original = r##"*foo bar -* -"##; - let expected = r##"

*foo bar -*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_348() { - let original = r##"*(*foo) -"##; - let expected = r##"

*(*foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_349() { - let original = r##"*(*foo*)* -"##; - let expected = r##"

(foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_350() { - let original = r##"*foo*bar -"##; - let expected = r##"

foobar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_351() { - let original = r##"_foo bar _ -"##; - let expected = r##"

_foo bar _

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_352() { - let original = r##"_(_foo) -"##; - let expected = r##"

_(_foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_353() { - let original = r##"_(_foo_)_ -"##; - let expected = r##"

(foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_354() { - let original = r##"_foo_bar -"##; - let expected = r##"

_foo_bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_355() { - let original = r##"_пристаням_стремятся -"##; - let expected = r##"

_пристаням_стремятся

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_356() { - let original = r##"_foo_bar_baz_ -"##; - let expected = r##"

foo_bar_baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_357() { - let original = r##"_(bar)_. -"##; - let expected = r##"

(bar).

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_358() { - let original = r##"**foo bar** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_359() { - let original = r##"** foo bar** -"##; - let expected = r##"

** foo bar**

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_360() { - let original = r##"a**"foo"** -"##; - let expected = r##"

a**"foo"**

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_361() { - let original = r##"foo**bar** -"##; - let expected = r##"

foobar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_362() { - let original = r##"__foo bar__ -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_363() { - let original = r##"__ foo bar__ -"##; - let expected = r##"

__ foo bar__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_364() { - let original = r##"__ -foo bar__ -"##; - let expected = r##"

__ -foo bar__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_365() { - let original = r##"a__"foo"__ -"##; - let expected = r##"

a__"foo"__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_366() { - let original = r##"foo__bar__ -"##; - let expected = r##"

foo__bar__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_367() { - let original = r##"5__6__78 -"##; - let expected = r##"

5__6__78

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_368() { - let original = r##"пристаням__стремятся__ -"##; - let expected = r##"

пристаням__стремятся__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_369() { - let original = r##"__foo, __bar__, baz__ -"##; - let expected = r##"

foo, bar, baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_370() { - let original = r##"foo-__(bar)__ -"##; - let expected = r##"

foo-(bar)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_371() { - let original = r##"**foo bar ** -"##; - let expected = r##"

**foo bar **

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_372() { - let original = r##"**(**foo) -"##; - let expected = r##"

**(**foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_373() { - let original = r##"*(**foo**)* -"##; - let expected = r##"

(foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_374() { - let original = r##"**Gomphocarpus (*Gomphocarpus physocarpus*, syn. -*Asclepias physocarpa*)** -"##; - let expected = r##"

Gomphocarpus (Gomphocarpus physocarpus, syn. -Asclepias physocarpa)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_375() { - let original = r##"**foo "*bar*" foo** -"##; - let expected = r##"

foo "bar" foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_376() { - let original = r##"**foo**bar -"##; - let expected = r##"

foobar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_377() { - let original = r##"__foo bar __ -"##; - let expected = r##"

__foo bar __

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_378() { - let original = r##"__(__foo) -"##; - let expected = r##"

__(__foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_379() { - let original = r##"_(__foo__)_ -"##; - let expected = r##"

(foo)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_380() { - let original = r##"__foo__bar -"##; - let expected = r##"

__foo__bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_381() { - let original = r##"__пристаням__стремятся -"##; - let expected = r##"

__пристаням__стремятся

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_382() { - let original = r##"__foo__bar__baz__ -"##; - let expected = r##"

foo__bar__baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_383() { - let original = r##"__(bar)__. -"##; - let expected = r##"

(bar).

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_384() { - let original = r##"*foo [bar](/url)* -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_385() { - let original = r##"*foo -bar* -"##; - let expected = r##"

foo -bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_386() { - let original = r##"_foo __bar__ baz_ -"##; - let expected = r##"

foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_387() { - let original = r##"_foo _bar_ baz_ -"##; - let expected = r##"

foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_388() { - let original = r##"__foo_ bar_ -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_389() { - let original = r##"*foo *bar** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_390() { - let original = r##"*foo **bar** baz* -"##; - let expected = r##"

foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_391() { - let original = r##"*foo**bar**baz* -"##; - let expected = r##"

foobarbaz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_392() { - let original = r##"***foo** bar* -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_393() { - let original = r##"*foo **bar*** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_394() { - let original = r##"*foo**bar*** -"##; - let expected = r##"

foobar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_395() { - let original = r##"*foo **bar *baz* bim** bop* -"##; - let expected = r##"

foo bar baz bim bop

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_396() { - let original = r##"*foo [*bar*](/url)* -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_397() { - let original = r##"** is not an empty emphasis -"##; - let expected = r##"

** is not an empty emphasis

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_398() { - let original = r##"**** is not an empty strong emphasis -"##; - let expected = r##"

**** is not an empty strong emphasis

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_399() { - let original = r##"**foo [bar](/url)** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_400() { - let original = r##"**foo -bar** -"##; - let expected = r##"

foo -bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_401() { - let original = r##"__foo _bar_ baz__ -"##; - let expected = r##"

foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_402() { - let original = r##"__foo __bar__ baz__ -"##; - let expected = r##"

foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_403() { - let original = r##"____foo__ bar__ -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_404() { - let original = r##"**foo **bar**** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_405() { - let original = r##"**foo *bar* baz** -"##; - let expected = r##"

foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_406() { - let original = r##"**foo*bar*baz** -"##; - let expected = r##"

foobarbaz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_407() { - let original = r##"***foo* bar** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_408() { - let original = r##"**foo *bar*** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_409() { - let original = r##"**foo *bar **baz** -bim* bop** -"##; - let expected = r##"

foo bar baz -bim bop

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_410() { - let original = r##"**foo [*bar*](/url)** -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_411() { - let original = r##"__ is not an empty emphasis -"##; - let expected = r##"

__ is not an empty emphasis

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_412() { - let original = r##"____ is not an empty strong emphasis -"##; - let expected = r##"

____ is not an empty strong emphasis

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_413() { - let original = r##"foo *** -"##; - let expected = r##"

foo ***

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_414() { - let original = r##"foo *\** -"##; - let expected = r##"

foo *

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_415() { - let original = r##"foo *_* -"##; - let expected = r##"

foo _

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_416() { - let original = r##"foo ***** -"##; - let expected = r##"

foo *****

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_417() { - let original = r##"foo **\*** -"##; - let expected = r##"

foo *

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_418() { - let original = r##"foo **_** -"##; - let expected = r##"

foo _

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_419() { - let original = r##"**foo* -"##; - let expected = r##"

*foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_420() { - let original = r##"*foo** -"##; - let expected = r##"

foo*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_421() { - let original = r##"***foo** -"##; - let expected = r##"

*foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_422() { - let original = r##"****foo* -"##; - let expected = r##"

***foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_423() { - let original = r##"**foo*** -"##; - let expected = r##"

foo*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_424() { - let original = r##"*foo**** -"##; - let expected = r##"

foo***

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_425() { - let original = r##"foo ___ -"##; - let expected = r##"

foo ___

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_426() { - let original = r##"foo _\__ -"##; - let expected = r##"

foo _

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_427() { - let original = r##"foo _*_ -"##; - let expected = r##"

foo *

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_428() { - let original = r##"foo _____ -"##; - let expected = r##"

foo _____

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_429() { - let original = r##"foo __\___ -"##; - let expected = r##"

foo _

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_430() { - let original = r##"foo __*__ -"##; - let expected = r##"

foo *

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_431() { - let original = r##"__foo_ -"##; - let expected = r##"

_foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_432() { - let original = r##"_foo__ -"##; - let expected = r##"

foo_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_433() { - let original = r##"___foo__ -"##; - let expected = r##"

_foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_434() { - let original = r##"____foo_ -"##; - let expected = r##"

___foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_435() { - let original = r##"__foo___ -"##; - let expected = r##"

foo_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_436() { - let original = r##"_foo____ -"##; - let expected = r##"

foo___

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_437() { - let original = r##"**foo** -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_438() { - let original = r##"*_foo_* -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_439() { - let original = r##"__foo__ -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_440() { - let original = r##"_*foo*_ -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_441() { - let original = r##"****foo**** -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_442() { - let original = r##"____foo____ -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_443() { - let original = r##"******foo****** -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_444() { - let original = r##"***foo*** -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_445() { - let original = r##"_____foo_____ -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_446() { - let original = r##"*foo _bar* baz_ -"##; - let expected = r##"

foo _bar baz_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_447() { - let original = r##"*foo __bar *baz bim__ bam* -"##; - let expected = r##"

foo bar *baz bim bam

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_448() { - let original = r##"**foo **bar baz** -"##; - let expected = r##"

**foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_449() { - let original = r##"*foo *bar baz* -"##; - let expected = r##"

*foo bar baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_450() { - let original = r##"*[bar*](/url) -"##; - let expected = r##"

*bar*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_451() { - let original = r##"_foo [bar_](/url) -"##; - let expected = r##"

_foo bar_

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_452() { - let original = r##"* -"##; - let expected = r##"

*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_453() { - let original = r##"** -"##; - let expected = r##"

**

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_454() { - let original = r##"__ -"##; - let expected = r##"

__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_455() { - let original = r##"*a `*`* -"##; - let expected = r##"

a *

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_456() { - let original = r##"_a `_`_ -"##; - let expected = r##"

a _

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_457() { - let original = r##"**a -"##; - let expected = r##"

**ahttp://foo.bar/?q=**

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_458() { - let original = r##"__a -"##; - let expected = r##"

__ahttp://foo.bar/?q=__

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_459() { - let original = r##"[link](/uri "title") -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_460() { - let original = r##"[link](/uri) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_461() { - let original = r##"[link]() -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_462() { - let original = r##"[link](<>) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_463() { - let original = r##"[link](/my uri) -"##; - let expected = r##"

[link](/my uri)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_464() { - let original = r##"[link]() -"##; - let expected = r##"

[link](</my uri>)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_465() { - let original = r##"[link](foo -bar) -"##; - let expected = r##"

[link](foo -bar)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_466() { - let original = r##"[link]() -"##; - let expected = r##"

[link]()

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_467() { - let original = r##"[link](\(foo\)) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_468() { - let original = r##"[link](foo(and(bar))) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_469() { - let original = r##"[link](foo\(and\(bar\)) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_470() { - let original = r##"[link]() -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_471() { - let original = r##"[link](foo\)\:) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_472() { - let original = r##"[link](#fragment) - -[link](http://example.com#fragment) - -[link](http://example.com?foo=3#frag) -"##; - let expected = r##"

link

-

link

-

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_473() { - let original = r##"[link](foo\bar) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_474() { - let original = r##"[link](foo%20bä) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_475() { - let original = r##"[link]("title") -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_476() { - let original = r##"[link](/url "title") -[link](/url 'title') -[link](/url (title)) -"##; - let expected = r##"

link -link -link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_477() { - let original = r##"[link](/url "title \""") -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_478() { - let original = r##"[link](/url "title") -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_479() { - let original = r##"[link](/url "title "and" title") -"##; - let expected = r##"

[link](/url "title "and" title")

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_480() { - let original = r##"[link](/url 'title "and" title') -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_481() { - let original = r##"[link]( /uri - "title" ) -"##; - let expected = r##"

link

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_482() { - let original = r##"[link] (/uri) -"##; - let expected = r##"

[link] (/uri)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_483() { - let original = r##"[link [foo [bar]]](/uri) -"##; - let expected = r##"

link [foo [bar]]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_484() { - let original = r##"[link] bar](/uri) -"##; - let expected = r##"

[link] bar](/uri)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_485() { - let original = r##"[link [bar](/uri) -"##; - let expected = r##"

[link bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_486() { - let original = r##"[link \[bar](/uri) -"##; - let expected = r##"

link [bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_487() { - let original = r##"[link *foo **bar** `#`*](/uri) -"##; - let expected = r##"

link foo bar #

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_488() { - let original = r##"[![moon](moon.jpg)](/uri) -"##; - let expected = r##"

moon

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_489() { - let original = r##"[foo [bar](/uri)](/uri) -"##; - let expected = r##"

[foo bar](/uri)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_490() { - let original = r##"[foo *[bar [baz](/uri)](/uri)*](/uri) -"##; - let expected = r##"

[foo [bar baz](/uri)](/uri)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_491() { - let original = r##"![[[foo](uri1)](uri2)](uri3) -"##; - let expected = r##"

[foo](uri2)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_492() { - let original = r##"*[foo*](/uri) -"##; - let expected = r##"

*foo*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_493() { - let original = r##"[foo *bar](baz*) -"##; - let expected = r##"

foo *bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_494() { - let original = r##"*foo [bar* baz] -"##; - let expected = r##"

foo [bar baz]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_495() { - let original = r##"[foo -"##; - let expected = r##"

[foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_496() { - let original = r##"[foo`](/uri)` -"##; - let expected = r##"

[foo](/uri)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_497() { - let original = r##"[foo -"##; - let expected = r##"

[foohttp://example.com/?search=](uri)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_498() { - let original = r##"[foo][bar] - -[bar]: /url "title" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_499() { - let original = r##"[link [foo [bar]]][ref] - -[ref]: /uri -"##; - let expected = r##"

link [foo [bar]]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_500() { - let original = r##"[link \[bar][ref] - -[ref]: /uri -"##; - let expected = r##"

link [bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_501() { - let original = r##"[link *foo **bar** `#`*][ref] - -[ref]: /uri -"##; - let expected = r##"

link foo bar #

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_502() { - let original = r##"[![moon](moon.jpg)][ref] - -[ref]: /uri -"##; - let expected = r##"

moon

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_503() { - let original = r##"[foo [bar](/uri)][ref] - -[ref]: /uri -"##; - let expected = r##"

[foo bar]ref

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_504() { - let original = r##"[foo *bar [baz][ref]*][ref] - -[ref]: /uri -"##; - let expected = r##"

[foo bar baz]ref

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_505() { - let original = r##"*[foo*][ref] - -[ref]: /uri -"##; - let expected = r##"

*foo*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_506() { - let original = r##"[foo *bar][ref] - -[ref]: /uri -"##; - let expected = r##"

foo *bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_507() { - let original = r##"[foo - -[ref]: /uri -"##; - let expected = r##"

[foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_508() { - let original = r##"[foo`][ref]` - -[ref]: /uri -"##; - let expected = r##"

[foo][ref]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_509() { - let original = r##"[foo - -[ref]: /uri -"##; - let expected = r##"

[foohttp://example.com/?search=][ref]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_510() { - let original = r##"[foo][BaR] - -[bar]: /url "title" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_511() { - let original = r##"[Толпой][Толпой] is a Russian word. - -[ТОЛПОЙ]: /url -"##; - let expected = r##"

Толпой is a Russian word.

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_512() { - let original = r##"[Foo - bar]: /url - -[Baz][Foo bar] -"##; - let expected = r##"

Baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_513() { - let original = r##"[foo] [bar] - -[bar]: /url "title" -"##; - let expected = r##"

[foo] bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_514() { - let original = r##"[foo] -[bar] - -[bar]: /url "title" -"##; - let expected = r##"

[foo] -bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_515() { - let original = r##"[foo]: /url1 - -[foo]: /url2 - -[bar][foo] -"##; - let expected = r##"

bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_516() { - let original = r##"[bar][foo\!] - -[foo!]: /url -"##; - let expected = r##"

[bar][foo!]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_517() { - let original = r##"[foo][ref[] - -[ref[]: /uri -"##; - let expected = r##"

[foo][ref[]

-

[ref[]: /uri

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_518() { - let original = r##"[foo][ref[bar]] - -[ref[bar]]: /uri -"##; - let expected = r##"

[foo][ref[bar]]

-

[ref[bar]]: /uri

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_519() { - let original = r##"[[[foo]]] - -[[[foo]]]: /url -"##; - let expected = r##"

[[[foo]]]

-

[[[foo]]]: /url

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_520() { - let original = r##"[foo][ref\[] - -[ref\[]: /uri -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_521() { - let original = r##"[bar\\]: /uri - -[bar\\] -"##; - let expected = r##"

bar\

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_522() { - let original = r##"[] - -[]: /uri -"##; - let expected = r##"

[]

-

[]: /uri

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_523() { - let original = r##"[ - ] - -[ - ]: /uri -"##; - let expected = r##"

[ -]

-

[ -]: /uri

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_524() { - let original = r##"[foo][] - -[foo]: /url "title" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_525() { - let original = r##"[*foo* bar][] - -[*foo* bar]: /url "title" -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_526() { - let original = r##"[Foo][] - -[foo]: /url "title" -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_527() { - let original = r##"[foo] -[] - -[foo]: /url "title" -"##; - let expected = r##"

foo -[]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_528() { - let original = r##"[foo] - -[foo]: /url "title" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_529() { - let original = r##"[*foo* bar] - -[*foo* bar]: /url "title" -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_530() { - let original = r##"[[*foo* bar]] - -[*foo* bar]: /url "title" -"##; - let expected = r##"

[foo bar]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_531() { - let original = r##"[[bar [foo] - -[foo]: /url -"##; - let expected = r##"

[[bar foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_532() { - let original = r##"[Foo] - -[foo]: /url "title" -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_533() { - let original = r##"[foo] bar - -[foo]: /url -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_534() { - let original = r##"\[foo] - -[foo]: /url "title" -"##; - let expected = r##"

[foo]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_535() { - let original = r##"[foo*]: /url - -*[foo*] -"##; - let expected = r##"

*foo*

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_536() { - let original = r##"[foo][bar] - -[foo]: /url1 -[bar]: /url2 -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_537() { - let original = r##"[foo][] - -[foo]: /url1 -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_538() { - let original = r##"[foo]() - -[foo]: /url1 -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_539() { - let original = r##"[foo](not a link) - -[foo]: /url1 -"##; - let expected = r##"

foo(not a link)

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_540() { - let original = r##"[foo][bar][baz] - -[baz]: /url -"##; - let expected = r##"

[foo]bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_541() { - let original = r##"[foo][bar][baz] - -[baz]: /url1 -[bar]: /url2 -"##; - let expected = r##"

foobaz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_542() { - let original = r##"[foo][bar][baz] - -[baz]: /url1 -[foo]: /url2 -"##; - let expected = r##"

[foo]bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_543() { - let original = r##"![foo](/url "title") -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_544() { - let original = r##"![foo *bar*] - -[foo *bar*]: train.jpg "train & tracks" -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_545() { - let original = r##"![foo ![bar](/url)](/url2) -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_546() { - let original = r##"![foo [bar](/url)](/url2) -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_547() { - let original = r##"![foo *bar*][] - -[foo *bar*]: train.jpg "train & tracks" -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_548() { - let original = r##"![foo *bar*][foobar] - -[FOOBAR]: train.jpg "train & tracks" -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_549() { - let original = r##"![foo](train.jpg) -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_550() { - let original = r##"My ![foo bar](/path/to/train.jpg "title" ) -"##; - let expected = r##"

My foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_551() { - let original = r##"![foo]() -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_552() { - let original = r##"![](/url) -"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_553() { - let original = r##"![foo][bar] - -[bar]: /url -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_554() { - let original = r##"![foo][bar] - -[BAR]: /url -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_555() { - let original = r##"![foo][] - -[foo]: /url "title" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_556() { - let original = r##"![*foo* bar][] - -[*foo* bar]: /url "title" -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_557() { - let original = r##"![Foo][] - -[foo]: /url "title" -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_558() { - let original = r##"![foo] -[] - -[foo]: /url "title" -"##; - let expected = r##"

foo -[]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_559() { - let original = r##"![foo] - -[foo]: /url "title" -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_560() { - let original = r##"![*foo* bar] - -[*foo* bar]: /url "title" -"##; - let expected = r##"

foo bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_561() { - let original = r##"![[foo]] - -[[foo]]: /url "title" -"##; - let expected = r##"

![[foo]]

-

[[foo]]: /url "title"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_562() { - let original = r##"![Foo] - -[foo]: /url "title" -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_563() { - let original = r##"!\[foo] - -[foo]: /url "title" -"##; - let expected = r##"

![foo]

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_564() { - let original = r##"\![foo] - -[foo]: /url "title" -"##; - let expected = r##"

!foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_565() { - let original = r##" -"##; - let expected = r##"

http://foo.bar.baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_566() { - let original = r##" -"##; - let expected = r##"

http://foo.bar.baz/test?q=hello&id=22&boolean

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_567() { - let original = r##" -"##; - let expected = r##"

irc://foo.bar:2233/baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_568() { - let original = r##" -"##; - let expected = r##"

MAILTO:FOO@BAR.BAZ

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_569() { - let original = r##" -"##; - let expected = r##"

a+b+c:d

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_570() { - let original = r##" -"##; - let expected = r##"

made-up-scheme://foo,bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_571() { - let original = r##" -"##; - let expected = r##"

http://../

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_572() { - let original = r##" -"##; - let expected = r##"

localhost:5001/foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_573() { - let original = r##" -"##; - let expected = r##"

<http://foo.bar/baz bim>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_574() { - let original = r##" -"##; - let expected = r##"

http://example.com/\[\

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_575() { - let original = r##" -"##; - let expected = r##"

foo@bar.example.com

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_576() { - let original = r##" -"##; - let expected = r##"

foo+special@Bar.baz-bar0.com

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_577() { - let original = r##" -"##; - let expected = r##"

<foo+@bar.example.com>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_578() { - let original = r##"<> -"##; - let expected = r##"

<>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_579() { - let original = r##"< http://foo.bar > -"##; - let expected = r##"

< http://foo.bar >

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_580() { - let original = r##" -"##; - let expected = r##"

<m:abc>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_581() { - let original = r##" -"##; - let expected = r##"

<foo.bar.baz>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_582() { - let original = r##"http://example.com -"##; - let expected = r##"

http://example.com

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_583() { - let original = r##"foo@bar.example.com -"##; - let expected = r##"

foo@bar.example.com

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_584() { - let original = r##" -"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_585() { - let original = r##" -"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_586() { - let original = r##" -"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_587() { - let original = r##" -"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_588() { - let original = r##"Foo -"##; - let expected = r##"

Foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_589() { - let original = r##"<33> <__> -"##; - let expected = r##"

<33> <__>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_590() { - let original = r##"
-"##; - let expected = r##"

<a h*#ref="hi">

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_591() { - let original = r##"
<a href="hi'> <a href=hi'>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_592() { - let original = r##"< a>< -foo> -"##; - let expected = r##"

< a>< -foo><bar/ >

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_593() { - let original = r##"
-"##; - let expected = r##"

<a href='bar'title=title>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_594() { - let original = r##"
-"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_595() { - let original = r##" -"##; - let expected = r##"

</a href="foo">

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_596() { - let original = r##"foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_597() { - let original = r##"foo -"##; - let expected = r##"

foo <!-- not a comment -- two hyphens -->

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_598() { - let original = r##"foo foo --> - -foo -"##; - let expected = r##"

foo <!--> foo -->

-

foo <!-- foo--->

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_599() { - let original = r##"foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_600() { - let original = r##"foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_601() { - let original = r##"foo &<]]> -"##; - let expected = r##"

foo &<]]>

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_602() { - let original = r##"foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_603() { - let original = r##"foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_604() { - let original = r##" -"##; - let expected = r##"

<a href=""">

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_605() { - let original = r##"foo -baz -"##; - let expected = r##"

foo
-baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_606() { - let original = r##"foo\ -baz -"##; - let expected = r##"

foo
-baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_607() { - let original = r##"foo -baz -"##; - let expected = r##"

foo
-baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_608() { - let original = r##"foo - bar -"##; - let expected = r##"

foo
-bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_609() { - let original = r##"foo\ - bar -"##; - let expected = r##"

foo
-bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_610() { - let original = r##"*foo -bar* -"##; - let expected = r##"

foo
-bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_611() { - let original = r##"*foo\ -bar* -"##; - let expected = r##"

foo
-bar

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_612() { - let original = r##"`code -span` -"##; - let expected = r##"

code span

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_613() { - let original = r##"`code\ -span` -"##; - let expected = r##"

code\ span

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_614() { - let original = r##"
-"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_615() { - let original = r##" -"##; - let expected = r##"

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_616() { - let original = r##"foo\ -"##; - let expected = r##"

foo\

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_617() { - let original = r##"foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_618() { - let original = r##"### foo\ -"##; - let expected = r##"

foo\

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_619() { - let original = r##"### foo -"##; - let expected = r##"

foo

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_620() { - let original = r##"foo -baz -"##; - let expected = r##"

foo -baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_621() { - let original = r##"foo - baz -"##; - let expected = r##"

foo -baz

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_622() { - let original = r##"hello $.;'there -"##; - let expected = r##"

hello $.;'there

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_623() { - let original = r##"Foo χρῆν -"##; - let expected = r##"

Foo χρῆν

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn spec_test_624() { - let original = r##"Multiple spaces -"##; - let expected = r##"

Multiple spaces

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } \ No newline at end of file diff --git a/vendor/pulldown-cmark-0.1.2/tests/table.rs b/vendor/pulldown-cmark-0.1.2/tests/table.rs deleted file mode 100644 index 7582a874c0..0000000000 --- a/vendor/pulldown-cmark-0.1.2/tests/table.rs +++ /dev/null @@ -1,368 +0,0 @@ -// This file is auto-generated by the build script -// Please, do not modify it manually - -extern crate pulldown_cmark; - - - #[test] - fn table_test_1() { - let original = r##"Test header ------------ -"##; - let expected = r##"

Test header

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_2() { - let original = r##"Test|Table -----|----- -"##; - let expected = r##" -
TestTable
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_3() { - let original = r##"Test|Table -----|----- -Test row -Test|2 - -Test ending -"##; - let expected = r##" - - -
TestTable
Test row
Test2
-

Test ending

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_4() { - let original = r##"> Test | Table -> ------|------ -> Row 1 | Every -> Row 2 | Day -> -> Paragraph -"##; - let expected = r##"
- - - -
Test Table
Row 1 Every
Row 2 Day
-

Paragraph

-
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_5() { - let original = r##" 1. First entry - 2. Second entry - - Col 1|Col 2 - -|- - Row 1|Part 2 - Row 2|Part 2 -"##; - let expected = r##"
    -
  1. -

    First entry

    -
  2. -
  3. -

    Second entry

    - - - -
    Col 1Col 2
    Row 1Part 2
    Row 2Part 2
    -
  4. -
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_6() { - let original = r##"|Col 1|Col 2| -|-----|-----| -|R1C1 |R1C2 | -|R2C1 |R2C2 | -"##; - let expected = r##" - - -
Col 1Col 2
R1C1 R1C2
R2C1 R2C2
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_7() { - let original = r##"| Col 1 | Col 2 | -|-------|-------| -| | | -| | | -"##; - let expected = r##" - - -
Col 1 Col 2
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_8() { - let original = r##"| Col 1 | Col 2 | -|-------|-------| -| x | | -| | x | -"##; - let expected = r##" - - -
Col 1 Col 2
x
x
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_9() { - let original = r##"|Col 1|Col 2| -|-----|-----| -|✓ |✓ | -|✓ |✓ | -"##; - let expected = r##" - - -
Col 1Col 2
✓ ✓
✓ ✓
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_10() { - let original = r##"| Target | std |rustc|cargo| notes | -|-------------------------------|-----|-----|-----|----------------------------| -| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL | -| `arm-linux-androideabi` | ✓ | | | ARM Android | -| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) | -| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) | -| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) | -"##; - let expected = r##" - - - - - - - -
Target std rustccargo notes
x86_64-unknown-linux-musl ✓ 64-bit Linux with MUSL
arm-linux-androideabi ✓ ARM Android
arm-unknown-linux-gnueabi ✓ ✓ ARM Linux (2.6.18+)
arm-unknown-linux-gnueabihf ✓ ✓ ARM Linux (2.6.18+)
aarch64-unknown-linux-gnu ✓ ARM64 Linux (2.6.18+)
mips-unknown-linux-gnu ✓ MIPS Linux (2.6.18+)
mipsel-unknown-linux-gnu ✓ MIPS (LE) Linux (2.6.18+)
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_11() { - let original = r##"|-|-| -|ぃ|い| -"##; - let expected = r##"

|-|-| -|ぃ|い|

-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_12() { - let original = r##"|ぁ|ぃ| -|-|-| -|ぃ|ぃ| -"##; - let expected = r##" - -
ぁぃ
ぃぃ
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } - - #[test] - fn table_test_13() { - let original = r##"|Колонка 1|Колонка 2| -|---------|---------| -|Ячейка 1 |Ячейка 2 | -"##; - let expected = r##" - -
Колонка 1Колонка 2
Ячейка 1 Ячейка 2
-"##; - - use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - } \ No newline at end of file diff --git a/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/LICENSE b/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/LICENSE deleted file mode 100644 index 6b8a93c5e3..0000000000 --- a/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/LICENSE +++ /dev/null @@ -1,105 +0,0 @@ -The CommonMark spec (spec.txt) and DTD (CommonMark.dtd) are - -Copyright (C) 2014-16 John MacFarlane - -Released under the Creative Commons CC-BY-SA 4.0 license: -. - -Creative Commons Attribution-ShareAlike 4.0 International Public License - -By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. - -Section 1 – Definitions. - -Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. -Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. -BY-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License. -Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. -Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. -Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. -License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution and ShareAlike. -Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. -Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. -Licensor means the individual(s) or entity(ies) granting rights under this Public License. -Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. -Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. -You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. -Section 2 – Scope. - -License grant. -Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: -reproduce and Share the Licensed Material, in whole or in part; and -produce, reproduce, and Share Adapted Material. -Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. -Term. The term of this Public License is specified in Section 6(a). -Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. -Downstream recipients. -Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. -Additional offer from the Licensor – Adapted Material. Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply. -No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. -No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). -Other rights. - -Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. -Patent and trademark rights are not licensed under this Public License. -To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. -Section 3 – License Conditions. - -Your exercise of the Licensed Rights is expressly made subject to the following conditions. - -Attribution. - -If You Share the Licensed Material (including in modified form), You must: - -retain the following if it is supplied by the Licensor with the Licensed Material: -identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); -a copyright notice; -a notice that refers to this Public License; -a notice that refers to the disclaimer of warranties; -a URI or hyperlink to the Licensed Material to the extent reasonably practicable; -indicate if You modified the Licensed Material and retain an indication of any previous modifications; and -indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. -You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. -If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. -ShareAlike. -In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply. - -The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-SA Compatible License. -You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material. -You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply. -Section 4 – Sui Generis Database Rights. - -Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: - -for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; -if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and -You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. -For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. -Section 5 – Disclaimer of Warranties and Limitation of Liability. - -Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. -To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. -The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. -Section 6 – Term and Termination. - -This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. -Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: - -automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or -upon express reinstatement by the Licensor. -For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. -For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. -Sections 1, 5, 6, 7, and 8 survive termination of this Public License. -Section 7 – Other Terms and Conditions. - -The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. -Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. -Section 8 – Interpretation. - -For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. -To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. -No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. -Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. -Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. - -Creative Commons may be contacted at creativecommons.org. \ No newline at end of file diff --git a/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/README.google b/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/README.google deleted file mode 100644 index 7ad133e415..0000000000 --- a/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/README.google +++ /dev/null @@ -1,12 +0,0 @@ -URL: https://github.com/jgm/CommonMark.git -Version: 1ef46a73e61968a60cc7b2e700381d719165b86c -License: Creative Commons CC-BY-SA 4.0 -License File: LICENSE - -Description: -CommonMark spec - -Local Modifications: -This directory contains only the spec file. License file has been -subsetted to only the files it applies to, and text of CC-BY-SA 4.0 -license has been added. diff --git a/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/spec.txt b/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/spec.txt deleted file mode 100644 index 9fd5841397..0000000000 --- a/vendor/pulldown-cmark-0.1.2/third_party/CommonMark/spec.txt +++ /dev/null @@ -1,9414 +0,0 @@ ---- -title: CommonMark Spec -author: John MacFarlane -version: 0.28 -date: '2017-08-01' -license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)' -... - -# Introduction - -## What is Markdown? - -Markdown is a plain text format for writing structured documents, -based on conventions for indicating formatting in email -and usenet posts. It was developed by John Gruber (with -help from Aaron Swartz) and released in 2004 in the form of a -[syntax description](http://daringfireball.net/projects/markdown/syntax) -and a Perl script (`Markdown.pl`) for converting Markdown to -HTML. In the next decade, dozens of implementations were -developed in many languages. Some extended the original -Markdown syntax with conventions for footnotes, tables, and -other document elements. Some allowed Markdown documents to be -rendered in formats other than HTML. Websites like Reddit, -StackOverflow, and GitHub had millions of people using Markdown. -And Markdown started to be used beyond the web, to author books, -articles, slide shows, letters, and lecture notes. - -What distinguishes Markdown from many other lightweight markup -syntaxes, which are often easier to write, is its readability. -As Gruber writes: - -> The overriding design goal for Markdown's formatting syntax is -> to make it as readable as possible. The idea is that a -> Markdown-formatted document should be publishable as-is, as -> plain text, without looking like it's been marked up with tags -> or formatting instructions. -> () - -The point can be illustrated by comparing a sample of -[AsciiDoc](http://www.methods.co.nz/asciidoc/) with -an equivalent sample of Markdown. Here is a sample of -AsciiDoc from the AsciiDoc manual: - -``` -1. List item one. -+ -List item one continued with a second paragraph followed by an -Indented block. -+ -................. -$ ls *.sh -$ mv *.sh ~/tmp -................. -+ -List item continued with a third paragraph. - -2. List item two continued with an open block. -+ --- -This paragraph is part of the preceding list item. - -a. This list is nested and does not require explicit item -continuation. -+ -This paragraph is part of the preceding list item. - -b. List item b. - -This paragraph belongs to item two of the outer list. --- -``` - -And here is the equivalent in Markdown: -``` -1. List item one. - - List item one continued with a second paragraph followed by an - Indented block. - - $ ls *.sh - $ mv *.sh ~/tmp - - List item continued with a third paragraph. - -2. List item two continued with an open block. - - This paragraph is part of the preceding list item. - - 1. This list is nested and does not require explicit item continuation. - - This paragraph is part of the preceding list item. - - 2. List item b. - - This paragraph belongs to item two of the outer list. -``` - -The AsciiDoc version is, arguably, easier to write. You don't need -to worry about indentation. But the Markdown version is much easier -to read. The nesting of list items is apparent to the eye in the -source, not just in the processed document. - -## Why is a spec needed? - -John Gruber's [canonical description of Markdown's -syntax](http://daringfireball.net/projects/markdown/syntax) -does not specify the syntax unambiguously. Here are some examples of -questions it does not answer: - -1. How much indentation is needed for a sublist? The spec says that - continuation paragraphs need to be indented four spaces, but is - not fully explicit about sublists. It is natural to think that - they, too, must be indented four spaces, but `Markdown.pl` does - not require that. This is hardly a "corner case," and divergences - between implementations on this issue often lead to surprises for - users in real documents. (See [this comment by John - Gruber](http://article.gmane.org/gmane.text.markdown.general/1997).) - -2. Is a blank line needed before a block quote or heading? - Most implementations do not require the blank line. However, - this can lead to unexpected results in hard-wrapped text, and - also to ambiguities in parsing (note that some implementations - put the heading inside the blockquote, while others do not). - (John Gruber has also spoken [in favor of requiring the blank - lines](http://article.gmane.org/gmane.text.markdown.general/2146).) - -3. Is a blank line needed before an indented code block? - (`Markdown.pl` requires it, but this is not mentioned in the - documentation, and some implementations do not require it.) - - ``` markdown - paragraph - code? - ``` - -4. What is the exact rule for determining when list items get - wrapped in `

` tags? Can a list be partially "loose" and partially - "tight"? What should we do with a list like this? - - ``` markdown - 1. one - - 2. two - 3. three - ``` - - Or this? - - ``` markdown - 1. one - - a - - - b - 2. two - ``` - - (There are some relevant comments by John Gruber - [here](http://article.gmane.org/gmane.text.markdown.general/2554).) - -5. Can list markers be indented? Can ordered list markers be right-aligned? - - ``` markdown - 8. item 1 - 9. item 2 - 10. item 2a - ``` - -6. Is this one list with a thematic break in its second item, - or two lists separated by a thematic break? - - ``` markdown - * a - * * * * * - * b - ``` - -7. When list markers change from numbers to bullets, do we have - two lists or one? (The Markdown syntax description suggests two, - but the perl scripts and many other implementations produce one.) - - ``` markdown - 1. fee - 2. fie - - foe - - fum - ``` - -8. What are the precedence rules for the markers of inline structure? - For example, is the following a valid link, or does the code span - take precedence ? - - ``` markdown - [a backtick (`)](/url) and [another backtick (`)](/url). - ``` - -9. What are the precedence rules for markers of emphasis and strong - emphasis? For example, how should the following be parsed? - - ``` markdown - *foo *bar* baz* - ``` - -10. What are the precedence rules between block-level and inline-level - structure? For example, how should the following be parsed? - - ``` markdown - - `a long code span can contain a hyphen like this - - and it can screw things up` - ``` - -11. Can list items include section headings? (`Markdown.pl` does not - allow this, but does allow blockquotes to include headings.) - - ``` markdown - - # Heading - ``` - -12. Can list items be empty? - - ``` markdown - * a - * - * b - ``` - -13. Can link references be defined inside block quotes or list items? - - ``` markdown - > Blockquote [foo]. - > - > [foo]: /url - ``` - -14. If there are multiple definitions for the same reference, which takes - precedence? - - ``` markdown - [foo]: /url1 - [foo]: /url2 - - [foo][] - ``` - -In the absence of a spec, early implementers consulted `Markdown.pl` -to resolve these ambiguities. But `Markdown.pl` was quite buggy, and -gave manifestly bad results in many cases, so it was not a -satisfactory replacement for a spec. - -Because there is no unambiguous spec, implementations have diverged -considerably. As a result, users are often surprised to find that -a document that renders one way on one system (say, a github wiki) -renders differently on another (say, converting to docbook using -pandoc). To make matters worse, because nothing in Markdown counts -as a "syntax error," the divergence often isn't discovered right away. - -## About this document - -This document attempts to specify Markdown syntax unambiguously. -It contains many examples with side-by-side Markdown and -HTML. These are intended to double as conformance tests. An -accompanying script `spec_tests.py` can be used to run the tests -against any Markdown program: - - python test/spec_tests.py --spec spec.txt --program PROGRAM - -Since this document describes how Markdown is to be parsed into -an abstract syntax tree, it would have made sense to use an abstract -representation of the syntax tree instead of HTML. But HTML is capable -of representing the structural distinctions we need to make, and the -choice of HTML for the tests makes it possible to run the tests against -an implementation without writing an abstract syntax tree renderer. - -This document is generated from a text file, `spec.txt`, written -in Markdown with a small extension for the side-by-side tests. -The script `tools/makespec.py` can be used to convert `spec.txt` into -HTML or CommonMark (which can then be converted into other formats). - -In the examples, the `→` character is used to represent tabs. - -# Preliminaries - -## Characters and lines - -Any sequence of [characters] is a valid CommonMark -document. - -A [character](@) is a Unicode code point. Although some -code points (for example, combining accents) do not correspond to -characters in an intuitive sense, all code points count as characters -for purposes of this spec. - -This spec does not specify an encoding; it thinks of lines as composed -of [characters] rather than bytes. A conforming parser may be limited -to a certain encoding. - -A [line](@) is a sequence of zero or more [characters] -other than newline (`U+000A`) or carriage return (`U+000D`), -followed by a [line ending] or by the end of file. - -A [line ending](@) is a newline (`U+000A`), a carriage return -(`U+000D`) not followed by a newline, or a carriage return and a -following newline. - -A line containing no characters, or a line containing only spaces -(`U+0020`) or tabs (`U+0009`), is called a [blank line](@). - -The following definitions of character classes will be used in this spec: - -A [whitespace character](@) is a space -(`U+0020`), tab (`U+0009`), newline (`U+000A`), line tabulation (`U+000B`), -form feed (`U+000C`), or carriage return (`U+000D`). - -[Whitespace](@) is a sequence of one or more [whitespace -characters]. - -A [Unicode whitespace character](@) is -any code point in the Unicode `Zs` general category, or a tab (`U+0009`), -carriage return (`U+000D`), newline (`U+000A`), or form feed -(`U+000C`). - -[Unicode whitespace](@) is a sequence of one -or more [Unicode whitespace characters]. - -A [space](@) is `U+0020`. - -A [non-whitespace character](@) is any character -that is not a [whitespace character]. - -An [ASCII punctuation character](@) -is `!`, `"`, `#`, `$`, `%`, `&`, `'`, `(`, `)`, -`*`, `+`, `,`, `-`, `.`, `/`, `:`, `;`, `<`, `=`, `>`, `?`, `@`, -`[`, `\`, `]`, `^`, `_`, `` ` ``, `{`, `|`, `}`, or `~`. - -A [punctuation character](@) is an [ASCII -punctuation character] or anything in -the general Unicode categories `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`. - -## Tabs - -Tabs in lines are not expanded to [spaces]. However, -in contexts where whitespace helps to define block structure, -tabs behave as if they were replaced by spaces with a tab stop -of 4 characters. - -Thus, for example, a tab can be used instead of four spaces -in an indented code block. (Note, however, that internal -tabs are passed through as literal tabs, not expanded to -spaces.) - -```````````````````````````````` example -→foo→baz→→bim -. -

foo→baz→→bim
-
-```````````````````````````````` - -```````````````````````````````` example - →foo→baz→→bim -. -
foo→baz→→bim
-
-```````````````````````````````` - -```````````````````````````````` example - a→a - ὐ→a -. -
a→a
-ὐ→a
-
-```````````````````````````````` - -In the following example, a continuation paragraph of a list -item is indented with a tab; this has exactly the same effect -as indentation with four spaces would: - -```````````````````````````````` example - - foo - -→bar -. -
    -
  • -

    foo

    -

    bar

    -
  • -
-```````````````````````````````` - -```````````````````````````````` example -- foo - -→→bar -. -
    -
  • -

    foo

    -
      bar
    -
    -
  • -
-```````````````````````````````` - -Normally the `>` that begins a block quote may be followed -optionally by a space, which is not considered part of the -content. In the following case `>` is followed by a tab, -which is treated as if it were expanded into three spaces. -Since one of these spaces is considered part of the -delimiter, `foo` is considered to be indented six spaces -inside the block quote context, so we get an indented -code block starting with two spaces. - -```````````````````````````````` example ->→→foo -. -
-
  foo
-
-
-```````````````````````````````` - -```````````````````````````````` example --→→foo -. -
    -
  • -
      foo
    -
    -
  • -
-```````````````````````````````` - - -```````````````````````````````` example - foo -→bar -. -
foo
-bar
-
-```````````````````````````````` - -```````````````````````````````` example - - foo - - bar -→ - baz -. -
    -
  • foo -
      -
    • bar -
        -
      • baz
      • -
      -
    • -
    -
  • -
-```````````````````````````````` - -```````````````````````````````` example -#→Foo -. -

Foo

-```````````````````````````````` - -```````````````````````````````` example -*→*→*→ -. -
-```````````````````````````````` - - -## Insecure characters - -For security reasons, the Unicode character `U+0000` must be replaced -with the REPLACEMENT CHARACTER (`U+FFFD`). - -# Blocks and inlines - -We can think of a document as a sequence of -[blocks](@)---structural elements like paragraphs, block -quotations, lists, headings, rules, and code blocks. Some blocks (like -block quotes and list items) contain other blocks; others (like -headings and paragraphs) contain [inline](@) content---text, -links, emphasized text, images, code spans, and so on. - -## Precedence - -Indicators of block structure always take precedence over indicators -of inline structure. So, for example, the following is a list with -two items, not a list with one item containing a code span: - -```````````````````````````````` example -- `one -- two` -. -
    -
  • `one
  • -
  • two`
  • -
-```````````````````````````````` - - -This means that parsing can proceed in two steps: first, the block -structure of the document can be discerned; second, text lines inside -paragraphs, headings, and other block constructs can be parsed for inline -structure. The second step requires information about link reference -definitions that will be available only at the end of the first -step. Note that the first step requires processing lines in sequence, -but the second can be parallelized, since the inline parsing of -one block element does not affect the inline parsing of any other. - -## Container blocks and leaf blocks - -We can divide blocks into two types: -[container block](@)s, -which can contain other blocks, and [leaf block](@)s, -which cannot. - -# Leaf blocks - -This section describes the different kinds of leaf block that make up a -Markdown document. - -## Thematic breaks - -A line consisting of 0-3 spaces of indentation, followed by a sequence -of three or more matching `-`, `_`, or `*` characters, each followed -optionally by any number of spaces, forms a -[thematic break](@). - -```````````````````````````````` example -*** ---- -___ -. -
-
-
-```````````````````````````````` - - -Wrong characters: - -```````````````````````````````` example -+++ -. -

+++

-```````````````````````````````` - - -```````````````````````````````` example -=== -. -

===

-```````````````````````````````` - - -Not enough characters: - -```````````````````````````````` example --- -** -__ -. -

-- -** -__

-```````````````````````````````` - - -One to three spaces indent are allowed: - -```````````````````````````````` example - *** - *** - *** -. -
-
-
-```````````````````````````````` - - -Four spaces is too many: - -```````````````````````````````` example - *** -. -
***
-
-```````````````````````````````` - - -```````````````````````````````` example -Foo - *** -. -

Foo -***

-```````````````````````````````` - - -More than three characters may be used: - -```````````````````````````````` example -_____________________________________ -. -
-```````````````````````````````` - - -Spaces are allowed between the characters: - -```````````````````````````````` example - - - - -. -
-```````````````````````````````` - - -```````````````````````````````` example - ** * ** * ** * ** -. -
-```````````````````````````````` - - -```````````````````````````````` example -- - - - -. -
-```````````````````````````````` - - -Spaces are allowed at the end: - -```````````````````````````````` example -- - - - -. -
-```````````````````````````````` - - -However, no other characters may occur in the line: - -```````````````````````````````` example -_ _ _ _ a - -a------ - ----a--- -. -

_ _ _ _ a

-

a------

-

---a---

-```````````````````````````````` - - -It is required that all of the [non-whitespace characters] be the same. -So, this is not a thematic break: - -```````````````````````````````` example - *-* -. -

-

-```````````````````````````````` - - -Thematic breaks do not need blank lines before or after: - -```````````````````````````````` example -- foo -*** -- bar -. -
    -
  • foo
  • -
-
-
    -
  • bar
  • -
-```````````````````````````````` - - -Thematic breaks can interrupt a paragraph: - -```````````````````````````````` example -Foo -*** -bar -. -

Foo

-
-

bar

-```````````````````````````````` - - -If a line of dashes that meets the above conditions for being a -thematic break could also be interpreted as the underline of a [setext -heading], the interpretation as a -[setext heading] takes precedence. Thus, for example, -this is a setext heading, not a paragraph followed by a thematic break: - -```````````````````````````````` example -Foo ---- -bar -. -

Foo

-

bar

-```````````````````````````````` - - -When both a thematic break and a list item are possible -interpretations of a line, the thematic break takes precedence: - -```````````````````````````````` example -* Foo -* * * -* Bar -. -
    -
  • Foo
  • -
-
-
    -
  • Bar
  • -
-```````````````````````````````` - - -If you want a thematic break in a list item, use a different bullet: - -```````````````````````````````` example -- Foo -- * * * -. -
    -
  • Foo
  • -
  • -
    -
  • -
-```````````````````````````````` - - -## ATX headings - -An [ATX heading](@) -consists of a string of characters, parsed as inline content, between an -opening sequence of 1--6 unescaped `#` characters and an optional -closing sequence of any number of unescaped `#` characters. -The opening sequence of `#` characters must be followed by a -[space] or by the end of line. The optional closing sequence of `#`s must be -preceded by a [space] and may be followed by spaces only. The opening -`#` character may be indented 0-3 spaces. The raw contents of the -heading are stripped of leading and trailing spaces before being parsed -as inline content. The heading level is equal to the number of `#` -characters in the opening sequence. - -Simple headings: - -```````````````````````````````` example -# foo -## foo -### foo -#### foo -##### foo -###### foo -. -

foo

-

foo

-

foo

-

foo

-
foo
-
foo
-```````````````````````````````` - - -More than six `#` characters is not a heading: - -```````````````````````````````` example -####### foo -. -

####### foo

-```````````````````````````````` - - -At least one space is required between the `#` characters and the -heading's contents, unless the heading is empty. Note that many -implementations currently do not require the space. However, the -space was required by the -[original ATX implementation](http://www.aaronsw.com/2002/atx/atx.py), -and it helps prevent things like the following from being parsed as -headings: - -```````````````````````````````` example -#5 bolt - -#hashtag -. -

#5 bolt

-

#hashtag

-```````````````````````````````` - - -This is not a heading, because the first `#` is escaped: - -```````````````````````````````` example -\## foo -. -

## foo

-```````````````````````````````` - - -Contents are parsed as inlines: - -```````````````````````````````` example -# foo *bar* \*baz\* -. -

foo bar *baz*

-```````````````````````````````` - - -Leading and trailing blanks are ignored in parsing inline content: - -```````````````````````````````` example -# foo -. -

foo

-```````````````````````````````` - - -One to three spaces indentation are allowed: - -```````````````````````````````` example - ### foo - ## foo - # foo -. -

foo

-

foo

-

foo

-```````````````````````````````` - - -Four spaces are too much: - -```````````````````````````````` example - # foo -. -
# foo
-
-```````````````````````````````` - - -```````````````````````````````` example -foo - # bar -. -

foo -# bar

-```````````````````````````````` - - -A closing sequence of `#` characters is optional: - -```````````````````````````````` example -## foo ## - ### bar ### -. -

foo

-

bar

-```````````````````````````````` - - -It need not be the same length as the opening sequence: - -```````````````````````````````` example -# foo ################################## -##### foo ## -. -

foo

-
foo
-```````````````````````````````` - - -Spaces are allowed after the closing sequence: - -```````````````````````````````` example -### foo ### -. -

foo

-```````````````````````````````` - - -A sequence of `#` characters with anything but [spaces] following it -is not a closing sequence, but counts as part of the contents of the -heading: - -```````````````````````````````` example -### foo ### b -. -

foo ### b

-```````````````````````````````` - - -The closing sequence must be preceded by a space: - -```````````````````````````````` example -# foo# -. -

foo#

-```````````````````````````````` - - -Backslash-escaped `#` characters do not count as part -of the closing sequence: - -```````````````````````````````` example -### foo \### -## foo #\## -# foo \# -. -

foo ###

-

foo ###

-

foo #

-```````````````````````````````` - - -ATX headings need not be separated from surrounding content by blank -lines, and they can interrupt paragraphs: - -```````````````````````````````` example -**** -## foo -**** -. -
-

foo

-
-```````````````````````````````` - - -```````````````````````````````` example -Foo bar -# baz -Bar foo -. -

Foo bar

-

baz

-

Bar foo

-```````````````````````````````` - - -ATX headings can be empty: - -```````````````````````````````` example -## -# -### ### -. -

-

-

-```````````````````````````````` - - -## Setext headings - -A [setext heading](@) consists of one or more -lines of text, each containing at least one [non-whitespace -character], with no more than 3 spaces indentation, followed by -a [setext heading underline]. The lines of text must be such -that, were they not followed by the setext heading underline, -they would be interpreted as a paragraph: they cannot be -interpretable as a [code fence], [ATX heading][ATX headings], -[block quote][block quotes], [thematic break][thematic breaks], -[list item][list items], or [HTML block][HTML blocks]. - -A [setext heading underline](@) is a sequence of -`=` characters or a sequence of `-` characters, with no more than 3 -spaces indentation and any number of trailing spaces. If a line -containing a single `-` can be interpreted as an -empty [list items], it should be interpreted this way -and not as a [setext heading underline]. - -The heading is a level 1 heading if `=` characters are used in -the [setext heading underline], and a level 2 heading if `-` -characters are used. The contents of the heading are the result -of parsing the preceding lines of text as CommonMark inline -content. - -In general, a setext heading need not be preceded or followed by a -blank line. However, it cannot interrupt a paragraph, so when a -setext heading comes after a paragraph, a blank line is needed between -them. - -Simple examples: - -```````````````````````````````` example -Foo *bar* -========= - -Foo *bar* ---------- -. -

Foo bar

-

Foo bar

-```````````````````````````````` - - -The content of the header may span more than one line: - -```````````````````````````````` example -Foo *bar -baz* -==== -. -

Foo bar -baz

-```````````````````````````````` - - -The underlining can be any length: - -```````````````````````````````` example -Foo -------------------------- - -Foo -= -. -

Foo

-

Foo

-```````````````````````````````` - - -The heading content can be indented up to three spaces, and need -not line up with the underlining: - -```````````````````````````````` example - Foo ---- - - Foo ------ - - Foo - === -. -

Foo

-

Foo

-

Foo

-```````````````````````````````` - - -Four spaces indent is too much: - -```````````````````````````````` example - Foo - --- - - Foo ---- -. -
Foo
----
-
-Foo
-
-
-```````````````````````````````` - - -The setext heading underline can be indented up to three spaces, and -may have trailing spaces: - -```````````````````````````````` example -Foo - ---- -. -

Foo

-```````````````````````````````` - - -Four spaces is too much: - -```````````````````````````````` example -Foo - --- -. -

Foo ----

-```````````````````````````````` - - -The setext heading underline cannot contain internal spaces: - -```````````````````````````````` example -Foo -= = - -Foo ---- - -. -

Foo -= =

-

Foo

-
-```````````````````````````````` - - -Trailing spaces in the content line do not cause a line break: - -```````````````````````````````` example -Foo ------ -. -

Foo

-```````````````````````````````` - - -Nor does a backslash at the end: - -```````````````````````````````` example -Foo\ ----- -. -

Foo\

-```````````````````````````````` - - -Since indicators of block structure take precedence over -indicators of inline structure, the following are setext headings: - -```````````````````````````````` example -`Foo ----- -` - -
-. -

`Foo

-

`

-

<a title="a lot

-

of dashes"/>

-```````````````````````````````` - - -The setext heading underline cannot be a [lazy continuation -line] in a list item or block quote: - -```````````````````````````````` example -> Foo ---- -. -
-

Foo

-
-
-```````````````````````````````` - - -```````````````````````````````` example -> foo -bar -=== -. -
-

foo -bar -===

-
-```````````````````````````````` - - -```````````````````````````````` example -- Foo ---- -. -
    -
  • Foo
  • -
-
-```````````````````````````````` - - -A blank line is needed between a paragraph and a following -setext heading, since otherwise the paragraph becomes part -of the heading's content: - -```````````````````````````````` example -Foo -Bar ---- -. -

Foo -Bar

-```````````````````````````````` - - -But in general a blank line is not required before or after -setext headings: - -```````````````````````````````` example ---- -Foo ---- -Bar ---- -Baz -. -
-

Foo

-

Bar

-

Baz

-```````````````````````````````` - - -Setext headings cannot be empty: - -```````````````````````````````` example - -==== -. -

====

-```````````````````````````````` - - -Setext heading text lines must not be interpretable as block -constructs other than paragraphs. So, the line of dashes -in these examples gets interpreted as a thematic break: - -```````````````````````````````` example ---- ---- -. -
-
-```````````````````````````````` - - -```````````````````````````````` example -- foo ------ -. -
    -
  • foo
  • -
-
-```````````````````````````````` - - -```````````````````````````````` example - foo ---- -. -
foo
-
-
-```````````````````````````````` - - -```````````````````````````````` example -> foo ------ -. -
-

foo

-
-
-```````````````````````````````` - - -If you want a heading with `> foo` as its literal text, you can -use backslash escapes: - -```````````````````````````````` example -\> foo ------- -. -

> foo

-```````````````````````````````` - - -**Compatibility note:** Most existing Markdown implementations -do not allow the text of setext headings to span multiple lines. -But there is no consensus about how to interpret - -``` markdown -Foo -bar ---- -baz -``` - -One can find four different interpretations: - -1. paragraph "Foo", heading "bar", paragraph "baz" -2. paragraph "Foo bar", thematic break, paragraph "baz" -3. paragraph "Foo bar --- baz" -4. heading "Foo bar", paragraph "baz" - -We find interpretation 4 most natural, and interpretation 4 -increases the expressive power of CommonMark, by allowing -multiline headings. Authors who want interpretation 1 can -put a blank line after the first paragraph: - -```````````````````````````````` example -Foo - -bar ---- -baz -. -

Foo

-

bar

-

baz

-```````````````````````````````` - - -Authors who want interpretation 2 can put blank lines around -the thematic break, - -```````````````````````````````` example -Foo -bar - ---- - -baz -. -

Foo -bar

-
-

baz

-```````````````````````````````` - - -or use a thematic break that cannot count as a [setext heading -underline], such as - -```````````````````````````````` example -Foo -bar -* * * -baz -. -

Foo -bar

-
-

baz

-```````````````````````````````` - - -Authors who want interpretation 3 can use backslash escapes: - -```````````````````````````````` example -Foo -bar -\--- -baz -. -

Foo -bar ---- -baz

-```````````````````````````````` - - -## Indented code blocks - -An [indented code block](@) is composed of one or more -[indented chunks] separated by blank lines. -An [indented chunk](@) is a sequence of non-blank lines, -each indented four or more spaces. The contents of the code block are -the literal contents of the lines, including trailing -[line endings], minus four spaces of indentation. -An indented code block has no [info string]. - -An indented code block cannot interrupt a paragraph, so there must be -a blank line between a paragraph and a following indented code block. -(A blank line is not needed, however, between a code block and a following -paragraph.) - -```````````````````````````````` example - a simple - indented code block -. -
a simple
-  indented code block
-
-```````````````````````````````` - - -If there is any ambiguity between an interpretation of indentation -as a code block and as indicating that material belongs to a [list -item][list items], the list item interpretation takes precedence: - -```````````````````````````````` example - - foo - - bar -. -
    -
  • -

    foo

    -

    bar

    -
  • -
-```````````````````````````````` - - -```````````````````````````````` example -1. foo - - - bar -. -
    -
  1. -

    foo

    -
      -
    • bar
    • -
    -
  2. -
-```````````````````````````````` - - - -The contents of a code block are literal text, and do not get parsed -as Markdown: - -```````````````````````````````` example -
- *hi* - - - one -. -
<a/>
-*hi*
-
-- one
-
-```````````````````````````````` - - -Here we have three chunks separated by blank lines: - -```````````````````````````````` example - chunk1 - - chunk2 - - - - chunk3 -. -
chunk1
-
-chunk2
-
-
-
-chunk3
-
-```````````````````````````````` - - -Any initial spaces beyond four will be included in the content, even -in interior blank lines: - -```````````````````````````````` example - chunk1 - - chunk2 -. -
chunk1
-  
-  chunk2
-
-```````````````````````````````` - - -An indented code block cannot interrupt a paragraph. (This -allows hanging indents and the like.) - -```````````````````````````````` example -Foo - bar - -. -

Foo -bar

-```````````````````````````````` - - -However, any non-blank line with fewer than four leading spaces ends -the code block immediately. So a paragraph may occur immediately -after indented code: - -```````````````````````````````` example - foo -bar -. -
foo
-
-

bar

-```````````````````````````````` - - -And indented code can occur immediately before and after other kinds of -blocks: - -```````````````````````````````` example -# Heading - foo -Heading ------- - foo ----- -. -

Heading

-
foo
-
-

Heading

-
foo
-
-
-```````````````````````````````` - - -The first line can be indented more than four spaces: - -```````````````````````````````` example - foo - bar -. -
    foo
-bar
-
-```````````````````````````````` - - -Blank lines preceding or following an indented code block -are not included in it: - -```````````````````````````````` example - - - foo - - -. -
foo
-
-```````````````````````````````` - - -Trailing spaces are included in the code block's content: - -```````````````````````````````` example - foo -. -
foo  
-
-```````````````````````````````` - - - -## Fenced code blocks - -A [code fence](@) is a sequence -of at least three consecutive backtick characters (`` ` ``) or -tildes (`~`). (Tildes and backticks cannot be mixed.) -A [fenced code block](@) -begins with a code fence, indented no more than three spaces. - -The line with the opening code fence may optionally contain some text -following the code fence; this is trimmed of leading and trailing -spaces and called the [info string](@). -The [info string] may not contain any backtick -characters. (The reason for this restriction is that otherwise -some inline code would be incorrectly interpreted as the -beginning of a fenced code block.) - -The content of the code block consists of all subsequent lines, until -a closing [code fence] of the same type as the code block -began with (backticks or tildes), and with at least as many backticks -or tildes as the opening code fence. If the leading code fence is -indented N spaces, then up to N spaces of indentation are removed from -each line of the content (if present). (If a content line is not -indented, it is preserved unchanged. If it is indented less than N -spaces, all of the indentation is removed.) - -The closing code fence may be indented up to three spaces, and may be -followed only by spaces, which are ignored. If the end of the -containing block (or document) is reached and no closing code fence -has been found, the code block contains all of the lines after the -opening code fence until the end of the containing block (or -document). (An alternative spec would require backtracking in the -event that a closing code fence is not found. But this makes parsing -much less efficient, and there seems to be no real down side to the -behavior described here.) - -A fenced code block may interrupt a paragraph, and does not require -a blank line either before or after. - -The content of a code fence is treated as literal text, not parsed -as inlines. The first word of the [info string] is typically used to -specify the language of the code sample, and rendered in the `class` -attribute of the `code` tag. However, this spec does not mandate any -particular treatment of the [info string]. - -Here is a simple example with backticks: - -```````````````````````````````` example -``` -< - > -``` -. -
<
- >
-
-```````````````````````````````` - - -With tildes: - -```````````````````````````````` example -~~~ -< - > -~~~ -. -
<
- >
-
-```````````````````````````````` - -Fewer than three backticks is not enough: - -```````````````````````````````` example -`` -foo -`` -. -

foo

-```````````````````````````````` - -The closing code fence must use the same character as the opening -fence: - -```````````````````````````````` example -``` -aaa -~~~ -``` -. -
aaa
-~~~
-
-```````````````````````````````` - - -```````````````````````````````` example -~~~ -aaa -``` -~~~ -. -
aaa
-```
-
-```````````````````````````````` - - -The closing code fence must be at least as long as the opening fence: - -```````````````````````````````` example -```` -aaa -``` -`````` -. -
aaa
-```
-
-```````````````````````````````` - - -```````````````````````````````` example -~~~~ -aaa -~~~ -~~~~ -. -
aaa
-~~~
-
-```````````````````````````````` - - -Unclosed code blocks are closed by the end of the document -(or the enclosing [block quote][block quotes] or [list item][list items]): - -```````````````````````````````` example -``` -. -
-```````````````````````````````` - - -```````````````````````````````` example -````` - -``` -aaa -. -

-```
-aaa
-
-```````````````````````````````` - - -```````````````````````````````` example -> ``` -> aaa - -bbb -. -
-
aaa
-
-
-

bbb

-```````````````````````````````` - - -A code block can have all empty lines as its content: - -```````````````````````````````` example -``` - - -``` -. -

-  
-
-```````````````````````````````` - - -A code block can be empty: - -```````````````````````````````` example -``` -``` -. -
-```````````````````````````````` - - -Fences can be indented. If the opening fence is indented, -content lines will have equivalent opening indentation removed, -if present: - -```````````````````````````````` example - ``` - aaa -aaa -``` -. -
aaa
-aaa
-
-```````````````````````````````` - - -```````````````````````````````` example - ``` -aaa - aaa -aaa - ``` -. -
aaa
-aaa
-aaa
-
-```````````````````````````````` - - -```````````````````````````````` example - ``` - aaa - aaa - aaa - ``` -. -
aaa
- aaa
-aaa
-
-```````````````````````````````` - - -Four spaces indentation produces an indented code block: - -```````````````````````````````` example - ``` - aaa - ``` -. -
```
-aaa
-```
-
-```````````````````````````````` - - -Closing fences may be indented by 0-3 spaces, and their indentation -need not match that of the opening fence: - -```````````````````````````````` example -``` -aaa - ``` -. -
aaa
-
-```````````````````````````````` - - -```````````````````````````````` example - ``` -aaa - ``` -. -
aaa
-
-```````````````````````````````` - - -This is not a closing fence, because it is indented 4 spaces: - -```````````````````````````````` example -``` -aaa - ``` -. -
aaa
-    ```
-
-```````````````````````````````` - - - -Code fences (opening and closing) cannot contain internal spaces: - -```````````````````````````````` example -``` ``` -aaa -. -

-aaa

-```````````````````````````````` - - -```````````````````````````````` example -~~~~~~ -aaa -~~~ ~~ -. -
aaa
-~~~ ~~
-
-```````````````````````````````` - - -Fenced code blocks can interrupt paragraphs, and can be followed -directly by paragraphs, without a blank line between: - -```````````````````````````````` example -foo -``` -bar -``` -baz -. -

foo

-
bar
-
-

baz

-```````````````````````````````` - - -Other blocks can also occur before and after fenced code blocks -without an intervening blank line: - -```````````````````````````````` example -foo ---- -~~~ -bar -~~~ -# baz -. -

foo

-
bar
-
-

baz

-```````````````````````````````` - - -An [info string] can be provided after the opening code fence. -Opening and closing spaces will be stripped, and the first word, prefixed -with `language-`, is used as the value for the `class` attribute of the -`code` element within the enclosing `pre` element. - -```````````````````````````````` example -```ruby -def foo(x) - return 3 -end -``` -. -
def foo(x)
-  return 3
-end
-
-```````````````````````````````` - - -```````````````````````````````` example -~~~~ ruby startline=3 $%@#$ -def foo(x) - return 3 -end -~~~~~~~ -. -
def foo(x)
-  return 3
-end
-
-```````````````````````````````` - - -```````````````````````````````` example -````; -```` -. -
-```````````````````````````````` - - -[Info strings] for backtick code blocks cannot contain backticks: - -```````````````````````````````` example -``` aa ``` -foo -. -

aa -foo

-```````````````````````````````` - - -Closing code fences cannot have [info strings]: - -```````````````````````````````` example -``` -``` aaa -``` -. -
``` aaa
-
-```````````````````````````````` - - - -## HTML blocks - -An [HTML block](@) is a group of lines that is treated -as raw HTML (and will not be escaped in HTML output). - -There are seven kinds of [HTML block], which can be defined -by their start and end conditions. The block begins with a line that -meets a [start condition](@) (after up to three spaces -optional indentation). It ends with the first subsequent line that -meets a matching [end condition](@), or the last line of -the document or other [container block]), if no line is encountered that meets the -[end condition]. If the first line meets both the [start condition] -and the [end condition], the block will contain just that line. - -1. **Start condition:** line begins with the string ``, or the end of the line.\ -**End condition:** line contains an end tag -``, ``, or `` (case-insensitive; it -need not match the start tag). - -2. **Start condition:** line begins with the string ``. - -3. **Start condition:** line begins with the string ``. - -4. **Start condition:** line begins with the string ``. - -5. **Start condition:** line begins with the string -``. - -6. **Start condition:** line begins the string `<` or ``, or -the string `/>`.\ -**End condition:** line is followed by a [blank line]. - -7. **Start condition:** line begins with a complete [open tag] -or [closing tag] (with any [tag name] other than `script`, -`style`, or `pre`) followed only by [whitespace] -or the end of the line.\ -**End condition:** line is followed by a [blank line]. - -HTML blocks continue until they are closed by their appropriate -[end condition], or the last line of the document or other [container block]. -This means any HTML **within an HTML block** that might otherwise be recognised -as a start condition will be ignored by the parser and passed through as-is, -without changing the parser's state. - -For instance, `
` within a HTML block started by `` will not affect
-the parser state; as the HTML block was started in by start condition 6, it
-will end at any blank line. This can be surprising:
-
-```````````````````````````````` example
-
-
-**Hello**,
-
-_world_.
-
-
-. -
-
-**Hello**,
-

world. -

-
-```````````````````````````````` - -In this case, the HTML block is terminated by the newline — the `**hello**` -text remains verbatim — and regular parsing resumes, with a paragraph, -emphasised `world` and inline and block HTML following. - -All types of [HTML blocks] except type 7 may interrupt -a paragraph. Blocks of type 7 may not interrupt a paragraph. -(This restriction is intended to prevent unwanted interpretation -of long tags inside a wrapped paragraph as starting HTML blocks.) - -Some simple examples follow. Here are some basic HTML blocks -of type 6: - -```````````````````````````````` example - - - - -
- hi -
- -okay. -. - - - - -
- hi -
-

okay.

-```````````````````````````````` - - -```````````````````````````````` example -
-*foo* -```````````````````````````````` - - -Here we have two HTML blocks with a Markdown paragraph between them: - -```````````````````````````````` example -
- -*Markdown* - -
-. -
-

Markdown

-
-```````````````````````````````` - - -The tag on the first line can be partial, as long -as it is split where there would be whitespace: - -```````````````````````````````` example -
-
-. -
-
-```````````````````````````````` - - -```````````````````````````````` example -
-
-. -
-
-```````````````````````````````` - - -An open tag need not be closed: -```````````````````````````````` example -
-*foo* - -*bar* -. -
-*foo* -

bar

-```````````````````````````````` - - - -A partial tag need not even be completed (garbage -in, garbage out): - -```````````````````````````````` example -
-. - -```````````````````````````````` - - -```````````````````````````````` example -
-foo -
-. -
-foo -
-```````````````````````````````` - - -Everything until the next blank line or end of document -gets included in the HTML block. So, in the following -example, what looks like a Markdown code block -is actually part of the HTML block, which continues until a blank -line or the end of the document is reached: - -```````````````````````````````` example -
-``` c -int x = 33; -``` -. -
-``` c -int x = 33; -``` -```````````````````````````````` - - -To start an [HTML block] with a tag that is *not* in the -list of block-level tags in (6), you must put the tag by -itself on the first line (and it must be complete): - -```````````````````````````````` example - -*bar* - -. - -*bar* - -```````````````````````````````` - - -In type 7 blocks, the [tag name] can be anything: - -```````````````````````````````` example - -*bar* - -. - -*bar* - -```````````````````````````````` - - -```````````````````````````````` example - -*bar* - -. - -*bar* - -```````````````````````````````` - - -```````````````````````````````` example - -*bar* -. - -*bar* -```````````````````````````````` - - -These rules are designed to allow us to work with tags that -can function as either block-level or inline-level tags. -The `` tag is a nice example. We can surround content with -`` tags in three different ways. In this case, we get a raw -HTML block, because the `` tag is on a line by itself: - -```````````````````````````````` example - -*foo* - -. - -*foo* - -```````````````````````````````` - - -In this case, we get a raw HTML block that just includes -the `` tag (because it ends with the following blank -line). So the contents get interpreted as CommonMark: - -```````````````````````````````` example - - -*foo* - - -. - -

foo

-
-```````````````````````````````` - - -Finally, in this case, the `` tags are interpreted -as [raw HTML] *inside* the CommonMark paragraph. (Because -the tag is not on a line by itself, we get inline HTML -rather than an [HTML block].) - -```````````````````````````````` example -*foo* -. -

foo

-```````````````````````````````` - - -HTML tags designed to contain literal content -(`script`, `style`, `pre`), comments, processing instructions, -and declarations are treated somewhat differently. -Instead of ending at the first blank line, these blocks -end at the first line containing a corresponding end tag. -As a result, these blocks can contain blank lines: - -A pre tag (type 1): - -```````````````````````````````` example -

-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-
-okay -. -

-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-
-

okay

-```````````````````````````````` - - -A script tag (type 1): - -```````````````````````````````` example - -okay -. - -

okay

-```````````````````````````````` - - -A style tag (type 1): - -```````````````````````````````` example - -okay -. - -

okay

-```````````````````````````````` - - -If there is no matching end tag, the block will end at the -end of the document (or the enclosing [block quote][block quotes] -or [list item][list items]): - -```````````````````````````````` example - -*foo* -. - -

foo

-```````````````````````````````` - - -```````````````````````````````` example -*bar* -*baz* -. -*bar* -

baz

-```````````````````````````````` - - -Note that anything on the last line after the -end tag will be included in the [HTML block]: - -```````````````````````````````` example -1. *bar* -. -1. *bar* -```````````````````````````````` - - -A comment (type 2): - -```````````````````````````````` example - -okay -. - -

okay

-```````````````````````````````` - - - -A processing instruction (type 3): - -```````````````````````````````` example -'; - -?> -okay -. -'; - -?> -

okay

-```````````````````````````````` - - -A declaration (type 4): - -```````````````````````````````` example - -. - -```````````````````````````````` - - -CDATA (type 5): - -```````````````````````````````` example - -okay -. - -

okay

-```````````````````````````````` - - -The opening tag can be indented 1-3 spaces, but not 4: - -```````````````````````````````` example - - - -. - -
<!-- foo -->
-
-```````````````````````````````` - - -```````````````````````````````` example -
- -
-. -
-
<div>
-
-```````````````````````````````` - - -An HTML block of types 1--6 can interrupt a paragraph, and need not be -preceded by a blank line. - -```````````````````````````````` example -Foo -
-bar -
-. -

Foo

-
-bar -
-```````````````````````````````` - - -However, a following blank line is needed, except at the end of -a document, and except for blocks of types 1--5, above: - -```````````````````````````````` example -
-bar -
-*foo* -. -
-bar -
-*foo* -```````````````````````````````` - - -HTML blocks of type 7 cannot interrupt a paragraph: - -```````````````````````````````` example -Foo - -baz -. -

Foo - -baz

-```````````````````````````````` - - -This rule differs from John Gruber's original Markdown syntax -specification, which says: - -> The only restrictions are that block-level HTML elements — -> e.g. `
`, ``, `
`, `

`, etc. — must be separated from -> surrounding content by blank lines, and the start and end tags of the -> block should not be indented with tabs or spaces. - -In some ways Gruber's rule is more restrictive than the one given -here: - -- It requires that an HTML block be preceded by a blank line. -- It does not allow the start tag to be indented. -- It requires a matching end tag, which it also does not allow to - be indented. - -Most Markdown implementations (including some of Gruber's own) do not -respect all of these restrictions. - -There is one respect, however, in which Gruber's rule is more liberal -than the one given here, since it allows blank lines to occur inside -an HTML block. There are two reasons for disallowing them here. -First, it removes the need to parse balanced tags, which is -expensive and can require backtracking from the end of the document -if no matching end tag is found. Second, it provides a very simple -and flexible way of including Markdown content inside HTML tags: -simply separate the Markdown from the HTML using blank lines: - -Compare: - -```````````````````````````````` example -

- -*Emphasized* text. - -
-. -
-

Emphasized text.

-
-```````````````````````````````` - - -```````````````````````````````` example -
-*Emphasized* text. -
-. -
-*Emphasized* text. -
-```````````````````````````````` - - -Some Markdown implementations have adopted a convention of -interpreting content inside tags as text if the open tag has -the attribute `markdown=1`. The rule given above seems a simpler and -more elegant way of achieving the same expressive power, which is also -much simpler to parse. - -The main potential drawback is that one can no longer paste HTML -blocks into Markdown documents with 100% reliability. However, -*in most cases* this will work fine, because the blank lines in -HTML are usually followed by HTML block tags. For example: - -```````````````````````````````` example -
- - - - - - - -
-Hi -
-. - - - - -
-Hi -
-```````````````````````````````` - - -There are problems, however, if the inner tags are indented -*and* separated by spaces, as then they will be interpreted as -an indented code block: - -```````````````````````````````` example - - - - - - - - -
- Hi -
-. - - -
<td>
-  Hi
-</td>
-
- -
-```````````````````````````````` - - -Fortunately, blank lines are usually not necessary and can be -deleted. The exception is inside `
` tags, but as described
-above, raw HTML blocks starting with `
` *can* contain blank
-lines.
-
-## Link reference definitions
-
-A [link reference definition](@)
-consists of a [link label], indented up to three spaces, followed
-by a colon (`:`), optional [whitespace] (including up to one
-[line ending]), a [link destination],
-optional [whitespace] (including up to one
-[line ending]), and an optional [link
-title], which if it is present must be separated
-from the [link destination] by [whitespace].
-No further [non-whitespace characters] may occur on the line.
-
-A [link reference definition]
-does not correspond to a structural element of a document.  Instead, it
-defines a label which can be used in [reference links]
-and reference-style [images] elsewhere in the document.  [Link
-reference definitions] can come either before or after the links that use
-them.
-
-```````````````````````````````` example
-[foo]: /url "title"
-
-[foo]
-.
-

foo

-```````````````````````````````` - - -```````````````````````````````` example - [foo]: - /url - 'the title' - -[foo] -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -[Foo*bar\]]:my_(url) 'title (with parens)' - -[Foo*bar\]] -. -

Foo*bar]

-```````````````````````````````` - - -```````````````````````````````` example -[Foo bar]: - -'title' - -[Foo bar] -. -

Foo bar

-```````````````````````````````` - - -The title may extend over multiple lines: - -```````````````````````````````` example -[foo]: /url ' -title -line1 -line2 -' - -[foo] -. -

foo

-```````````````````````````````` - - -However, it may not contain a [blank line]: - -```````````````````````````````` example -[foo]: /url 'title - -with blank line' - -[foo] -. -

[foo]: /url 'title

-

with blank line'

-

[foo]

-```````````````````````````````` - - -The title may be omitted: - -```````````````````````````````` example -[foo]: -/url - -[foo] -. -

foo

-```````````````````````````````` - - -The link destination may not be omitted: - -```````````````````````````````` example -[foo]: - -[foo] -. -

[foo]:

-

[foo]

-```````````````````````````````` - - -Both title and destination can contain backslash escapes -and literal backslashes: - -```````````````````````````````` example -[foo]: /url\bar\*baz "foo\"bar\baz" - -[foo] -. -

foo

-```````````````````````````````` - - -A link can come before its corresponding definition: - -```````````````````````````````` example -[foo] - -[foo]: url -. -

foo

-```````````````````````````````` - - -If there are several matching definitions, the first one takes -precedence: - -```````````````````````````````` example -[foo] - -[foo]: first -[foo]: second -. -

foo

-```````````````````````````````` - - -As noted in the section on [Links], matching of labels is -case-insensitive (see [matches]). - -```````````````````````````````` example -[FOO]: /url - -[Foo] -. -

Foo

-```````````````````````````````` - - -```````````````````````````````` example -[ΑΓΩ]: /φου - -[αγω] -. -

αγω

-```````````````````````````````` - - -Here is a link reference definition with no corresponding link. -It contributes nothing to the document. - -```````````````````````````````` example -[foo]: /url -. -```````````````````````````````` - - -Here is another one: - -```````````````````````````````` example -[ -foo -]: /url -bar -. -

bar

-```````````````````````````````` - - -This is not a link reference definition, because there are -[non-whitespace characters] after the title: - -```````````````````````````````` example -[foo]: /url "title" ok -. -

[foo]: /url "title" ok

-```````````````````````````````` - - -This is a link reference definition, but it has no title: - -```````````````````````````````` example -[foo]: /url -"title" ok -. -

"title" ok

-```````````````````````````````` - - -This is not a link reference definition, because it is indented -four spaces: - -```````````````````````````````` example - [foo]: /url "title" - -[foo] -. -
[foo]: /url "title"
-
-

[foo]

-```````````````````````````````` - - -This is not a link reference definition, because it occurs inside -a code block: - -```````````````````````````````` example -``` -[foo]: /url -``` - -[foo] -. -
[foo]: /url
-
-

[foo]

-```````````````````````````````` - - -A [link reference definition] cannot interrupt a paragraph. - -```````````````````````````````` example -Foo -[bar]: /baz - -[bar] -. -

Foo -[bar]: /baz

-

[bar]

-```````````````````````````````` - - -However, it can directly follow other block elements, such as headings -and thematic breaks, and it need not be followed by a blank line. - -```````````````````````````````` example -# [Foo] -[foo]: /url -> bar -. -

Foo

-
-

bar

-
-```````````````````````````````` - - -Several [link reference definitions] -can occur one after another, without intervening blank lines. - -```````````````````````````````` example -[foo]: /foo-url "foo" -[bar]: /bar-url - "bar" -[baz]: /baz-url - -[foo], -[bar], -[baz] -. -

foo, -bar, -baz

-```````````````````````````````` - - -[Link reference definitions] can occur -inside block containers, like lists and block quotations. They -affect the entire document, not just the container in which they -are defined: - -```````````````````````````````` example -[foo] - -> [foo]: /url -. -

foo

-
-
-```````````````````````````````` - - - -## Paragraphs - -A sequence of non-blank lines that cannot be interpreted as other -kinds of blocks forms a [paragraph](@). -The contents of the paragraph are the result of parsing the -paragraph's raw content as inlines. The paragraph's raw content -is formed by concatenating the lines and removing initial and final -[whitespace]. - -A simple example with two paragraphs: - -```````````````````````````````` example -aaa - -bbb -. -

aaa

-

bbb

-```````````````````````````````` - - -Paragraphs can contain multiple lines, but no blank lines: - -```````````````````````````````` example -aaa -bbb - -ccc -ddd -. -

aaa -bbb

-

ccc -ddd

-```````````````````````````````` - - -Multiple blank lines between paragraph have no effect: - -```````````````````````````````` example -aaa - - -bbb -. -

aaa

-

bbb

-```````````````````````````````` - - -Leading spaces are skipped: - -```````````````````````````````` example - aaa - bbb -. -

aaa -bbb

-```````````````````````````````` - - -Lines after the first may be indented any amount, since indented -code blocks cannot interrupt paragraphs. - -```````````````````````````````` example -aaa - bbb - ccc -. -

aaa -bbb -ccc

-```````````````````````````````` - - -However, the first line may be indented at most three spaces, -or an indented code block will be triggered: - -```````````````````````````````` example - aaa -bbb -. -

aaa -bbb

-```````````````````````````````` - - -```````````````````````````````` example - aaa -bbb -. -
aaa
-
-

bbb

-```````````````````````````````` - - -Final spaces are stripped before inline parsing, so a paragraph -that ends with two or more spaces will not end with a [hard line -break]: - -```````````````````````````````` example -aaa -bbb -. -

aaa
-bbb

-```````````````````````````````` - - -## Blank lines - -[Blank lines] between block-level elements are ignored, -except for the role they play in determining whether a [list] -is [tight] or [loose]. - -Blank lines at the beginning and end of the document are also ignored. - -```````````````````````````````` example - - -aaa - - -# aaa - - -. -

aaa

-

aaa

-```````````````````````````````` - - - -# Container blocks - -A [container block] is a block that has other -blocks as its contents. There are two basic kinds of container blocks: -[block quotes] and [list items]. -[Lists] are meta-containers for [list items]. - -We define the syntax for container blocks recursively. The general -form of the definition is: - -> If X is a sequence of blocks, then the result of -> transforming X in such-and-such a way is a container of type Y -> with these blocks as its content. - -So, we explain what counts as a block quote or list item by explaining -how these can be *generated* from their contents. This should suffice -to define the syntax, although it does not give a recipe for *parsing* -these constructions. (A recipe is provided below in the section entitled -[A parsing strategy](#appendix-a-parsing-strategy).) - -## Block quotes - -A [block quote marker](@) -consists of 0-3 spaces of initial indent, plus (a) the character `>` together -with a following space, or (b) a single character `>` not followed by a space. - -The following rules define [block quotes]: - -1. **Basic case.** If a string of lines *Ls* constitute a sequence - of blocks *Bs*, then the result of prepending a [block quote - marker] to the beginning of each line in *Ls* - is a [block quote](#block-quotes) containing *Bs*. - -2. **Laziness.** If a string of lines *Ls* constitute a [block - quote](#block-quotes) with contents *Bs*, then the result of deleting - the initial [block quote marker] from one or - more lines in which the next [non-whitespace character] after the [block - quote marker] is [paragraph continuation - text] is a block quote with *Bs* as its content. - [Paragraph continuation text](@) is text - that will be parsed as part of the content of a paragraph, but does - not occur at the beginning of the paragraph. - -3. **Consecutiveness.** A document cannot contain two [block - quotes] in a row unless there is a [blank line] between them. - -Nothing else counts as a [block quote](#block-quotes). - -Here is a simple example: - -```````````````````````````````` example -> # Foo -> bar -> baz -. -
-

Foo

-

bar -baz

-
-```````````````````````````````` - - -The spaces after the `>` characters can be omitted: - -```````````````````````````````` example -># Foo ->bar -> baz -. -
-

Foo

-

bar -baz

-
-```````````````````````````````` - - -The `>` characters can be indented 1-3 spaces: - -```````````````````````````````` example - > # Foo - > bar - > baz -. -
-

Foo

-

bar -baz

-
-```````````````````````````````` - - -Four spaces gives us a code block: - -```````````````````````````````` example - > # Foo - > bar - > baz -. -
> # Foo
-> bar
-> baz
-
-```````````````````````````````` - - -The Laziness clause allows us to omit the `>` before -[paragraph continuation text]: - -```````````````````````````````` example -> # Foo -> bar -baz -. -
-

Foo

-

bar -baz

-
-```````````````````````````````` - - -A block quote can contain some lazy and some non-lazy -continuation lines: - -```````````````````````````````` example -> bar -baz -> foo -. -
-

bar -baz -foo

-
-```````````````````````````````` - - -Laziness only applies to lines that would have been continuations of -paragraphs had they been prepended with [block quote markers]. -For example, the `> ` cannot be omitted in the second line of - -``` markdown -> foo -> --- -``` - -without changing the meaning: - -```````````````````````````````` example -> foo ---- -. -
-

foo

-
-
-```````````````````````````````` - - -Similarly, if we omit the `> ` in the second line of - -``` markdown -> - foo -> - bar -``` - -then the block quote ends after the first line: - -```````````````````````````````` example -> - foo -- bar -. -
-
    -
  • foo
  • -
-
-
    -
  • bar
  • -
-```````````````````````````````` - - -For the same reason, we can't omit the `> ` in front of -subsequent lines of an indented or fenced code block: - -```````````````````````````````` example -> foo - bar -. -
-
foo
-
-
-
bar
-
-```````````````````````````````` - - -```````````````````````````````` example -> ``` -foo -``` -. -
-
-
-

foo

-
-```````````````````````````````` - - -Note that in the following case, we have a [lazy -continuation line]: - -```````````````````````````````` example -> foo - - bar -. -
-

foo -- bar

-
-```````````````````````````````` - - -To see why, note that in - -```markdown -> foo -> - bar -``` - -the `- bar` is indented too far to start a list, and can't -be an indented code block because indented code blocks cannot -interrupt paragraphs, so it is [paragraph continuation text]. - -A block quote can be empty: - -```````````````````````````````` example -> -. -
-
-```````````````````````````````` - - -```````````````````````````````` example -> -> -> -. -
-
-```````````````````````````````` - - -A block quote can have initial or final blank lines: - -```````````````````````````````` example -> -> foo -> -. -
-

foo

-
-```````````````````````````````` - - -A blank line always separates block quotes: - -```````````````````````````````` example -> foo - -> bar -. -
-

foo

-
-
-

bar

-
-```````````````````````````````` - - -(Most current Markdown implementations, including John Gruber's -original `Markdown.pl`, will parse this example as a single block quote -with two paragraphs. But it seems better to allow the author to decide -whether two block quotes or one are wanted.) - -Consecutiveness means that if we put these block quotes together, -we get a single block quote: - -```````````````````````````````` example -> foo -> bar -. -
-

foo -bar

-
-```````````````````````````````` - - -To get a block quote with two paragraphs, use: - -```````````````````````````````` example -> foo -> -> bar -. -
-

foo

-

bar

-
-```````````````````````````````` - - -Block quotes can interrupt paragraphs: - -```````````````````````````````` example -foo -> bar -. -

foo

-
-

bar

-
-```````````````````````````````` - - -In general, blank lines are not needed before or after block -quotes: - -```````````````````````````````` example -> aaa -*** -> bbb -. -
-

aaa

-
-
-
-

bbb

-
-```````````````````````````````` - - -However, because of laziness, a blank line is needed between -a block quote and a following paragraph: - -```````````````````````````````` example -> bar -baz -. -
-

bar -baz

-
-```````````````````````````````` - - -```````````````````````````````` example -> bar - -baz -. -
-

bar

-
-

baz

-```````````````````````````````` - - -```````````````````````````````` example -> bar -> -baz -. -
-

bar

-
-

baz

-```````````````````````````````` - - -It is a consequence of the Laziness rule that any number -of initial `>`s may be omitted on a continuation line of a -nested block quote: - -```````````````````````````````` example -> > > foo -bar -. -
-
-
-

foo -bar

-
-
-
-```````````````````````````````` - - -```````````````````````````````` example ->>> foo -> bar ->>baz -. -
-
-
-

foo -bar -baz

-
-
-
-```````````````````````````````` - - -When including an indented code block in a block quote, -remember that the [block quote marker] includes -both the `>` and a following space. So *five spaces* are needed after -the `>`: - -```````````````````````````````` example -> code - -> not code -. -
-
code
-
-
-
-

not code

-
-```````````````````````````````` - - - -## List items - -A [list marker](@) is a -[bullet list marker] or an [ordered list marker]. - -A [bullet list marker](@) -is a `-`, `+`, or `*` character. - -An [ordered list marker](@) -is a sequence of 1--9 arabic digits (`0-9`), followed by either a -`.` character or a `)` character. (The reason for the length -limit is that with 10 digits we start seeing integer overflows -in some browsers.) - -The following rules define [list items]: - -1. **Basic case.** If a sequence of lines *Ls* constitute a sequence of - blocks *Bs* starting with a [non-whitespace character] and not separated - from each other by more than one blank line, and *M* is a list - marker of width *W* followed by 1 ≤ *N* ≤ 4 spaces, then the result - of prepending *M* and the following spaces to the first line of - *Ls*, and indenting subsequent lines of *Ls* by *W + N* spaces, is a - list item with *Bs* as its contents. The type of the list item - (bullet or ordered) is determined by the type of its list marker. - If the list item is ordered, then it is also assigned a start - number, based on the ordered list marker. - - Exceptions: - - 1. When the first list item in a [list] interrupts - a paragraph---that is, when it starts on a line that would - otherwise count as [paragraph continuation text]---then (a) - the lines *Ls* must not begin with a blank line, and (b) if - the list item is ordered, the start number must be 1. - 2. If any line is a [thematic break][thematic breaks] then - that line is not a list item. - -For example, let *Ls* be the lines - -```````````````````````````````` example -A paragraph -with two lines. - - indented code - -> A block quote. -. -

A paragraph -with two lines.

-
indented code
-
-
-

A block quote.

-
-```````````````````````````````` - - -And let *M* be the marker `1.`, and *N* = 2. Then rule #1 says -that the following is an ordered list item with start number 1, -and the same contents as *Ls*: - -```````````````````````````````` example -1. A paragraph - with two lines. - - indented code - - > A block quote. -. -
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-```````````````````````````````` - - -The most important thing to notice is that the position of -the text after the list marker determines how much indentation -is needed in subsequent blocks in the list item. If the list -marker takes up two spaces, and there are three spaces between -the list marker and the next [non-whitespace character], then blocks -must be indented five spaces in order to fall under the list -item. - -Here are some examples showing how far content must be indented to be -put under the list item: - -```````````````````````````````` example -- one - - two -. -
    -
  • one
  • -
-

two

-```````````````````````````````` - - -```````````````````````````````` example -- one - - two -. -
    -
  • -

    one

    -

    two

    -
  • -
-```````````````````````````````` - - -```````````````````````````````` example - - one - - two -. -
    -
  • one
  • -
-
 two
-
-```````````````````````````````` - - -```````````````````````````````` example - - one - - two -. -
    -
  • -

    one

    -

    two

    -
  • -
-```````````````````````````````` - - -It is tempting to think of this in terms of columns: the continuation -blocks must be indented at least to the column of the first -[non-whitespace character] after the list marker. However, that is not quite right. -The spaces after the list marker determine how much relative indentation -is needed. Which column this indentation reaches will depend on -how the list item is embedded in other constructions, as shown by -this example: - -```````````````````````````````` example - > > 1. one ->> ->> two -. -
-
-
    -
  1. -

    one

    -

    two

    -
  2. -
-
-
-```````````````````````````````` - - -Here `two` occurs in the same column as the list marker `1.`, -but is actually contained in the list item, because there is -sufficient indentation after the last containing blockquote marker. - -The converse is also possible. In the following example, the word `two` -occurs far to the right of the initial text of the list item, `one`, but -it is not considered part of the list item, because it is not indented -far enough past the blockquote marker: - -```````````````````````````````` example ->>- one ->> - > > two -. -
-
-
    -
  • one
  • -
-

two

-
-
-```````````````````````````````` - - -Note that at least one space is needed between the list marker and -any following content, so these are not list items: - -```````````````````````````````` example --one - -2.two -. -

-one

-

2.two

-```````````````````````````````` - - -A list item may contain blocks that are separated by more than -one blank line. - -```````````````````````````````` example -- foo - - - bar -. -
    -
  • -

    foo

    -

    bar

    -
  • -
-```````````````````````````````` - - -A list item may contain any kind of block: - -```````````````````````````````` example -1. foo - - ``` - bar - ``` - - baz - - > bam -. -
    -
  1. -

    foo

    -
    bar
    -
    -

    baz

    -
    -

    bam

    -
    -
  2. -
-```````````````````````````````` - - -A list item that contains an indented code block will preserve -empty lines within the code block verbatim. - -```````````````````````````````` example -- Foo - - bar - - - baz -. -
    -
  • -

    Foo

    -
    bar
    -
    -
    -baz
    -
    -
  • -
-```````````````````````````````` - -Note that ordered list start numbers must be nine digits or less: - -```````````````````````````````` example -123456789. ok -. -
    -
  1. ok
  2. -
-```````````````````````````````` - - -```````````````````````````````` example -1234567890. not ok -. -

1234567890. not ok

-```````````````````````````````` - - -A start number may begin with 0s: - -```````````````````````````````` example -0. ok -. -
    -
  1. ok
  2. -
-```````````````````````````````` - - -```````````````````````````````` example -003. ok -. -
    -
  1. ok
  2. -
-```````````````````````````````` - - -A start number may not be negative: - -```````````````````````````````` example --1. not ok -. -

-1. not ok

-```````````````````````````````` - - - -2. **Item starting with indented code.** If a sequence of lines *Ls* - constitute a sequence of blocks *Bs* starting with an indented code - block and not separated from each other by more than one blank line, - and *M* is a list marker of width *W* followed by - one space, then the result of prepending *M* and the following - space to the first line of *Ls*, and indenting subsequent lines of - *Ls* by *W + 1* spaces, is a list item with *Bs* as its contents. - If a line is empty, then it need not be indented. The type of the - list item (bullet or ordered) is determined by the type of its list - marker. If the list item is ordered, then it is also assigned a - start number, based on the ordered list marker. - -An indented code block will have to be indented four spaces beyond -the edge of the region where text will be included in the list item. -In the following case that is 6 spaces: - -```````````````````````````````` example -- foo - - bar -. -
    -
  • -

    foo

    -
    bar
    -
    -
  • -
-```````````````````````````````` - - -And in this case it is 11 spaces: - -```````````````````````````````` example - 10. foo - - bar -. -
    -
  1. -

    foo

    -
    bar
    -
    -
  2. -
-```````````````````````````````` - - -If the *first* block in the list item is an indented code block, -then by rule #2, the contents must be indented *one* space after the -list marker: - -```````````````````````````````` example - indented code - -paragraph - - more code -. -
indented code
-
-

paragraph

-
more code
-
-```````````````````````````````` - - -```````````````````````````````` example -1. indented code - - paragraph - - more code -. -
    -
  1. -
    indented code
    -
    -

    paragraph

    -
    more code
    -
    -
  2. -
-```````````````````````````````` - - -Note that an additional space indent is interpreted as space -inside the code block: - -```````````````````````````````` example -1. indented code - - paragraph - - more code -. -
    -
  1. -
     indented code
    -
    -

    paragraph

    -
    more code
    -
    -
  2. -
-```````````````````````````````` - - -Note that rules #1 and #2 only apply to two cases: (a) cases -in which the lines to be included in a list item begin with a -[non-whitespace character], and (b) cases in which -they begin with an indented code -block. In a case like the following, where the first block begins with -a three-space indent, the rules do not allow us to form a list item by -indenting the whole thing and prepending a list marker: - -```````````````````````````````` example - foo - -bar -. -

foo

-

bar

-```````````````````````````````` - - -```````````````````````````````` example -- foo - - bar -. -
    -
  • foo
  • -
-

bar

-```````````````````````````````` - - -This is not a significant restriction, because when a block begins -with 1-3 spaces indent, the indentation can always be removed without -a change in interpretation, allowing rule #1 to be applied. So, in -the above case: - -```````````````````````````````` example -- foo - - bar -. -
    -
  • -

    foo

    -

    bar

    -
  • -
-```````````````````````````````` - - -3. **Item starting with a blank line.** If a sequence of lines *Ls* - starting with a single [blank line] constitute a (possibly empty) - sequence of blocks *Bs*, not separated from each other by more than - one blank line, and *M* is a list marker of width *W*, - then the result of prepending *M* to the first line of *Ls*, and - indenting subsequent lines of *Ls* by *W + 1* spaces, is a list - item with *Bs* as its contents. - If a line is empty, then it need not be indented. The type of the - list item (bullet or ordered) is determined by the type of its list - marker. If the list item is ordered, then it is also assigned a - start number, based on the ordered list marker. - -Here are some list items that start with a blank line but are not empty: - -```````````````````````````````` example -- - foo -- - ``` - bar - ``` -- - baz -. -
    -
  • foo
  • -
  • -
    bar
    -
    -
  • -
  • -
    baz
    -
    -
  • -
-```````````````````````````````` - -When the list item starts with a blank line, the number of spaces -following the list marker doesn't change the required indentation: - -```````````````````````````````` example -- - foo -. -
    -
  • foo
  • -
-```````````````````````````````` - - -A list item can begin with at most one blank line. -In the following example, `foo` is not part of the list -item: - -```````````````````````````````` example -- - - foo -. -
    -
  • -
-

foo

-```````````````````````````````` - - -Here is an empty bullet list item: - -```````````````````````````````` example -- foo -- -- bar -. -
    -
  • foo
  • -
  • -
  • bar
  • -
-```````````````````````````````` - - -It does not matter whether there are spaces following the [list marker]: - -```````````````````````````````` example -- foo -- -- bar -. -
    -
  • foo
  • -
  • -
  • bar
  • -
-```````````````````````````````` - - -Here is an empty ordered list item: - -```````````````````````````````` example -1. foo -2. -3. bar -. -
    -
  1. foo
  2. -
  3. -
  4. bar
  5. -
-```````````````````````````````` - - -A list may start or end with an empty list item: - -```````````````````````````````` example -* -. -
    -
  • -
-```````````````````````````````` - -However, an empty list item cannot interrupt a paragraph: - -```````````````````````````````` example -foo -* - -foo -1. -. -

foo -*

-

foo -1.

-```````````````````````````````` - - -4. **Indentation.** If a sequence of lines *Ls* constitutes a list item - according to rule #1, #2, or #3, then the result of indenting each line - of *Ls* by 1-3 spaces (the same for each line) also constitutes a - list item with the same contents and attributes. If a line is - empty, then it need not be indented. - -Indented one space: - -```````````````````````````````` example - 1. A paragraph - with two lines. - - indented code - - > A block quote. -. -
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-```````````````````````````````` - - -Indented two spaces: - -```````````````````````````````` example - 1. A paragraph - with two lines. - - indented code - - > A block quote. -. -
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-```````````````````````````````` - - -Indented three spaces: - -```````````````````````````````` example - 1. A paragraph - with two lines. - - indented code - - > A block quote. -. -
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-```````````````````````````````` - - -Four spaces indent gives a code block: - -```````````````````````````````` example - 1. A paragraph - with two lines. - - indented code - - > A block quote. -. -
1.  A paragraph
-    with two lines.
-
-        indented code
-
-    > A block quote.
-
-```````````````````````````````` - - - -5. **Laziness.** If a string of lines *Ls* constitute a [list - item](#list-items) with contents *Bs*, then the result of deleting - some or all of the indentation from one or more lines in which the - next [non-whitespace character] after the indentation is - [paragraph continuation text] is a - list item with the same contents and attributes. The unindented - lines are called - [lazy continuation line](@)s. - -Here is an example with [lazy continuation lines]: - -```````````````````````````````` example - 1. A paragraph -with two lines. - - indented code - - > A block quote. -. -
    -
  1. -

    A paragraph -with two lines.

    -
    indented code
    -
    -
    -

    A block quote.

    -
    -
  2. -
-```````````````````````````````` - - -Indentation can be partially deleted: - -```````````````````````````````` example - 1. A paragraph - with two lines. -. -
    -
  1. A paragraph -with two lines.
  2. -
-```````````````````````````````` - - -These examples show how laziness can work in nested structures: - -```````````````````````````````` example -> 1. > Blockquote -continued here. -. -
-
    -
  1. -
    -

    Blockquote -continued here.

    -
    -
  2. -
-
-```````````````````````````````` - - -```````````````````````````````` example -> 1. > Blockquote -> continued here. -. -
-
    -
  1. -
    -

    Blockquote -continued here.

    -
    -
  2. -
-
-```````````````````````````````` - - - -6. **That's all.** Nothing that is not counted as a list item by rules - #1--5 counts as a [list item](#list-items). - -The rules for sublists follow from the general rules above. A sublist -must be indented the same number of spaces a paragraph would need to be -in order to be included in the list item. - -So, in this case we need two spaces indent: - -```````````````````````````````` example -- foo - - bar - - baz - - boo -. -
    -
  • foo -
      -
    • bar -
        -
      • baz -
          -
        • boo
        • -
        -
      • -
      -
    • -
    -
  • -
-```````````````````````````````` - - -One is not enough: - -```````````````````````````````` example -- foo - - bar - - baz - - boo -. -
    -
  • foo
  • -
  • bar
  • -
  • baz
  • -
  • boo
  • -
-```````````````````````````````` - - -Here we need four, because the list marker is wider: - -```````````````````````````````` example -10) foo - - bar -. -
    -
  1. foo -
      -
    • bar
    • -
    -
  2. -
-```````````````````````````````` - - -Three is not enough: - -```````````````````````````````` example -10) foo - - bar -. -
    -
  1. foo
  2. -
-
    -
  • bar
  • -
-```````````````````````````````` - - -A list may be the first block in a list item: - -```````````````````````````````` example -- - foo -. -
    -
  • -
      -
    • foo
    • -
    -
  • -
-```````````````````````````````` - - -```````````````````````````````` example -1. - 2. foo -. -
    -
  1. -
      -
    • -
        -
      1. foo
      2. -
      -
    • -
    -
  2. -
-```````````````````````````````` - - -A list item can contain a heading: - -```````````````````````````````` example -- # Foo -- Bar - --- - baz -. -
    -
  • -

    Foo

    -
  • -
  • -

    Bar

    -baz
  • -
-```````````````````````````````` - - -### Motivation - -John Gruber's Markdown spec says the following about list items: - -1. "List markers typically start at the left margin, but may be indented - by up to three spaces. List markers must be followed by one or more - spaces or a tab." - -2. "To make lists look nice, you can wrap items with hanging indents.... - But if you don't want to, you don't have to." - -3. "List items may consist of multiple paragraphs. Each subsequent - paragraph in a list item must be indented by either 4 spaces or one - tab." - -4. "It looks nice if you indent every line of the subsequent paragraphs, - but here again, Markdown will allow you to be lazy." - -5. "To put a blockquote within a list item, the blockquote's `>` - delimiters need to be indented." - -6. "To put a code block within a list item, the code block needs to be - indented twice — 8 spaces or two tabs." - -These rules specify that a paragraph under a list item must be indented -four spaces (presumably, from the left margin, rather than the start of -the list marker, but this is not said), and that code under a list item -must be indented eight spaces instead of the usual four. They also say -that a block quote must be indented, but not by how much; however, the -example given has four spaces indentation. Although nothing is said -about other kinds of block-level content, it is certainly reasonable to -infer that *all* block elements under a list item, including other -lists, must be indented four spaces. This principle has been called the -*four-space rule*. - -The four-space rule is clear and principled, and if the reference -implementation `Markdown.pl` had followed it, it probably would have -become the standard. However, `Markdown.pl` allowed paragraphs and -sublists to start with only two spaces indentation, at least on the -outer level. Worse, its behavior was inconsistent: a sublist of an -outer-level list needed two spaces indentation, but a sublist of this -sublist needed three spaces. It is not surprising, then, that different -implementations of Markdown have developed very different rules for -determining what comes under a list item. (Pandoc and python-Markdown, -for example, stuck with Gruber's syntax description and the four-space -rule, while discount, redcarpet, marked, PHP Markdown, and others -followed `Markdown.pl`'s behavior more closely.) - -Unfortunately, given the divergences between implementations, there -is no way to give a spec for list items that will be guaranteed not -to break any existing documents. However, the spec given here should -correctly handle lists formatted with either the four-space rule or -the more forgiving `Markdown.pl` behavior, provided they are laid out -in a way that is natural for a human to read. - -The strategy here is to let the width and indentation of the list marker -determine the indentation necessary for blocks to fall under the list -item, rather than having a fixed and arbitrary number. The writer can -think of the body of the list item as a unit which gets indented to the -right enough to fit the list marker (and any indentation on the list -marker). (The laziness rule, #5, then allows continuation lines to be -unindented if needed.) - -This rule is superior, we claim, to any rule requiring a fixed level of -indentation from the margin. The four-space rule is clear but -unnatural. It is quite unintuitive that - -``` markdown -- foo - - bar - - - baz -``` - -should be parsed as two lists with an intervening paragraph, - -``` html -
    -
  • foo
  • -
-

bar

-
    -
  • baz
  • -
-``` - -as the four-space rule demands, rather than a single list, - -``` html -
    -
  • -

    foo

    -

    bar

    -
      -
    • baz
    • -
    -
  • -
-``` - -The choice of four spaces is arbitrary. It can be learned, but it is -not likely to be guessed, and it trips up beginners regularly. - -Would it help to adopt a two-space rule? The problem is that such -a rule, together with the rule allowing 1--3 spaces indentation of the -initial list marker, allows text that is indented *less than* the -original list marker to be included in the list item. For example, -`Markdown.pl` parses - -``` markdown - - one - - two -``` - -as a single list item, with `two` a continuation paragraph: - -``` html -
    -
  • -

    one

    -

    two

    -
  • -
-``` - -and similarly - -``` markdown -> - one -> -> two -``` - -as - -``` html -
-
    -
  • -

    one

    -

    two

    -
  • -
-
-``` - -This is extremely unintuitive. - -Rather than requiring a fixed indent from the margin, we could require -a fixed indent (say, two spaces, or even one space) from the list marker (which -may itself be indented). This proposal would remove the last anomaly -discussed. Unlike the spec presented above, it would count the following -as a list item with a subparagraph, even though the paragraph `bar` -is not indented as far as the first paragraph `foo`: - -``` markdown - 10. foo - - bar -``` - -Arguably this text does read like a list item with `bar` as a subparagraph, -which may count in favor of the proposal. However, on this proposal indented -code would have to be indented six spaces after the list marker. And this -would break a lot of existing Markdown, which has the pattern: - -``` markdown -1. foo - - indented code -``` - -where the code is indented eight spaces. The spec above, by contrast, will -parse this text as expected, since the code block's indentation is measured -from the beginning of `foo`. - -The one case that needs special treatment is a list item that *starts* -with indented code. How much indentation is required in that case, since -we don't have a "first paragraph" to measure from? Rule #2 simply stipulates -that in such cases, we require one space indentation from the list marker -(and then the normal four spaces for the indented code). This will match the -four-space rule in cases where the list marker plus its initial indentation -takes four spaces (a common case), but diverge in other cases. - -## Lists - -A [list](@) is a sequence of one or more -list items [of the same type]. The list items -may be separated by any number of blank lines. - -Two list items are [of the same type](@) -if they begin with a [list marker] of the same type. -Two list markers are of the -same type if (a) they are bullet list markers using the same character -(`-`, `+`, or `*`) or (b) they are ordered list numbers with the same -delimiter (either `.` or `)`). - -A list is an [ordered list](@) -if its constituent list items begin with -[ordered list markers], and a -[bullet list](@) if its constituent list -items begin with [bullet list markers]. - -The [start number](@) -of an [ordered list] is determined by the list number of -its initial list item. The numbers of subsequent list items are -disregarded. - -A list is [loose](@) if any of its constituent -list items are separated by blank lines, or if any of its constituent -list items directly contain two block-level elements with a blank line -between them. Otherwise a list is [tight](@). -(The difference in HTML output is that paragraphs in a loose list are -wrapped in `

` tags, while paragraphs in a tight list are not.) - -Changing the bullet or ordered list delimiter starts a new list: - -```````````````````````````````` example -- foo -- bar -+ baz -. -

    -
  • foo
  • -
  • bar
  • -
-
    -
  • baz
  • -
-```````````````````````````````` - - -```````````````````````````````` example -1. foo -2. bar -3) baz -. -
    -
  1. foo
  2. -
  3. bar
  4. -
-
    -
  1. baz
  2. -
-```````````````````````````````` - - -In CommonMark, a list can interrupt a paragraph. That is, -no blank line is needed to separate a paragraph from a following -list: - -```````````````````````````````` example -Foo -- bar -- baz -. -

Foo

-
    -
  • bar
  • -
  • baz
  • -
-```````````````````````````````` - -`Markdown.pl` does not allow this, through fear of triggering a list -via a numeral in a hard-wrapped line: - -``` markdown -The number of windows in my house is -14. The number of doors is 6. -``` - -Oddly, though, `Markdown.pl` *does* allow a blockquote to -interrupt a paragraph, even though the same considerations might -apply. - -In CommonMark, we do allow lists to interrupt paragraphs, for -two reasons. First, it is natural and not uncommon for people -to start lists without blank lines: - -``` markdown -I need to buy -- new shoes -- a coat -- a plane ticket -``` - -Second, we are attracted to a - -> [principle of uniformity](@): -> if a chunk of text has a certain -> meaning, it will continue to have the same meaning when put into a -> container block (such as a list item or blockquote). - -(Indeed, the spec for [list items] and [block quotes] presupposes -this principle.) This principle implies that if - -``` markdown - * I need to buy - - new shoes - - a coat - - a plane ticket -``` - -is a list item containing a paragraph followed by a nested sublist, -as all Markdown implementations agree it is (though the paragraph -may be rendered without `

` tags, since the list is "tight"), -then - -``` markdown -I need to buy -- new shoes -- a coat -- a plane ticket -``` - -by itself should be a paragraph followed by a nested sublist. - -Since it is well established Markdown practice to allow lists to -interrupt paragraphs inside list items, the [principle of -uniformity] requires us to allow this outside list items as -well. ([reStructuredText](http://docutils.sourceforge.net/rst.html) -takes a different approach, requiring blank lines before lists -even inside other list items.) - -In order to solve of unwanted lists in paragraphs with -hard-wrapped numerals, we allow only lists starting with `1` to -interrupt paragraphs. Thus, - -```````````````````````````````` example -The number of windows in my house is -14. The number of doors is 6. -. -

The number of windows in my house is -14. The number of doors is 6.

-```````````````````````````````` - -We may still get an unintended result in cases like - -```````````````````````````````` example -The number of windows in my house is -1. The number of doors is 6. -. -

The number of windows in my house is

-
    -
  1. The number of doors is 6.
  2. -
-```````````````````````````````` - -but this rule should prevent most spurious list captures. - -There can be any number of blank lines between items: - -```````````````````````````````` example -- foo - -- bar - - -- baz -. -
    -
  • -

    foo

    -
  • -
  • -

    bar

    -
  • -
  • -

    baz

    -
  • -
-```````````````````````````````` - -```````````````````````````````` example -- foo - - bar - - baz - - - bim -. -
    -
  • foo -
      -
    • bar -
        -
      • -

        baz

        -

        bim

        -
      • -
      -
    • -
    -
  • -
-```````````````````````````````` - - -To separate consecutive lists of the same type, or to separate a -list from an indented code block that would otherwise be parsed -as a subparagraph of the final list item, you can insert a blank HTML -comment: - -```````````````````````````````` example -- foo -- bar - - - -- baz -- bim -. -
    -
  • foo
  • -
  • bar
  • -
- -
    -
  • baz
  • -
  • bim
  • -
-```````````````````````````````` - - -```````````````````````````````` example -- foo - - notcode - -- foo - - - - code -. -
    -
  • -

    foo

    -

    notcode

    -
  • -
  • -

    foo

    -
  • -
- -
code
-
-```````````````````````````````` - - -List items need not be indented to the same level. The following -list items will be treated as items at the same list level, -since none is indented enough to belong to the previous list -item: - -```````````````````````````````` example -- a - - b - - c - - d - - e - - f - - g - - h -- i -. -
    -
  • a
  • -
  • b
  • -
  • c
  • -
  • d
  • -
  • e
  • -
  • f
  • -
  • g
  • -
  • h
  • -
  • i
  • -
-```````````````````````````````` - - -```````````````````````````````` example -1. a - - 2. b - - 3. c -. -
    -
  1. -

    a

    -
  2. -
  3. -

    b

    -
  4. -
  5. -

    c

    -
  6. -
-```````````````````````````````` - - -This is a loose list, because there is a blank line between -two of the list items: - -```````````````````````````````` example -- a -- b - -- c -. -
    -
  • -

    a

    -
  • -
  • -

    b

    -
  • -
  • -

    c

    -
  • -
-```````````````````````````````` - - -So is this, with a empty second item: - -```````````````````````````````` example -* a -* - -* c -. -
    -
  • -

    a

    -
  • -
  • -
  • -

    c

    -
  • -
-```````````````````````````````` - - -These are loose lists, even though there is no space between the items, -because one of the items directly contains two block-level elements -with a blank line between them: - -```````````````````````````````` example -- a -- b - - c -- d -. -
    -
  • -

    a

    -
  • -
  • -

    b

    -

    c

    -
  • -
  • -

    d

    -
  • -
-```````````````````````````````` - - -```````````````````````````````` example -- a -- b - - [ref]: /url -- d -. -
    -
  • -

    a

    -
  • -
  • -

    b

    -
  • -
  • -

    d

    -
  • -
-```````````````````````````````` - - -This is a tight list, because the blank lines are in a code block: - -```````````````````````````````` example -- a -- ``` - b - - - ``` -- c -. -
    -
  • a
  • -
  • -
    b
    -
    -
    -
    -
  • -
  • c
  • -
-```````````````````````````````` - - -This is a tight list, because the blank line is between two -paragraphs of a sublist. So the sublist is loose while -the outer list is tight: - -```````````````````````````````` example -- a - - b - - c -- d -. -
    -
  • a -
      -
    • -

      b

      -

      c

      -
    • -
    -
  • -
  • d
  • -
-```````````````````````````````` - - -This is a tight list, because the blank line is inside the -block quote: - -```````````````````````````````` example -* a - > b - > -* c -. -
    -
  • a -
    -

    b

    -
    -
  • -
  • c
  • -
-```````````````````````````````` - - -This list is tight, because the consecutive block elements -are not separated by blank lines: - -```````````````````````````````` example -- a - > b - ``` - c - ``` -- d -. -
    -
  • a -
    -

    b

    -
    -
    c
    -
    -
  • -
  • d
  • -
-```````````````````````````````` - - -A single-paragraph list is tight: - -```````````````````````````````` example -- a -. -
    -
  • a
  • -
-```````````````````````````````` - - -```````````````````````````````` example -- a - - b -. -
    -
  • a -
      -
    • b
    • -
    -
  • -
-```````````````````````````````` - - -This list is loose, because of the blank line between the -two block elements in the list item: - -```````````````````````````````` example -1. ``` - foo - ``` - - bar -. -
    -
  1. -
    foo
    -
    -

    bar

    -
  2. -
-```````````````````````````````` - - -Here the outer list is loose, the inner list tight: - -```````````````````````````````` example -* foo - * bar - - baz -. -
    -
  • -

    foo

    -
      -
    • bar
    • -
    -

    baz

    -
  • -
-```````````````````````````````` - - -```````````````````````````````` example -- a - - b - - c - -- d - - e - - f -. -
    -
  • -

    a

    -
      -
    • b
    • -
    • c
    • -
    -
  • -
  • -

    d

    -
      -
    • e
    • -
    • f
    • -
    -
  • -
-```````````````````````````````` - - -# Inlines - -Inlines are parsed sequentially from the beginning of the character -stream to the end (left to right, in left-to-right languages). -Thus, for example, in - -```````````````````````````````` example -`hi`lo` -. -

hilo`

-```````````````````````````````` - - -`hi` is parsed as code, leaving the backtick at the end as a literal -backtick. - -## Backslash escapes - -Any ASCII punctuation character may be backslash-escaped: - -```````````````````````````````` example -\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~ -. -

!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

-```````````````````````````````` - - -Backslashes before other characters are treated as literal -backslashes: - -```````````````````````````````` example -\→\A\a\ \3\φ\« -. -

\→\A\a\ \3\φ\«

-```````````````````````````````` - - -Escaped characters are treated as regular characters and do -not have their usual Markdown meanings: - -```````````````````````````````` example -\*not emphasized* -\
not a tag -\[not a link](/foo) -\`not code` -1\. not a list -\* not a list -\# not a heading -\[foo]: /url "not a reference" -. -

*not emphasized* -<br/> not a tag -[not a link](/foo) -`not code` -1. not a list -* not a list -# not a heading -[foo]: /url "not a reference"

-```````````````````````````````` - - -If a backslash is itself escaped, the following character is not: - -```````````````````````````````` example -\\*emphasis* -. -

\emphasis

-```````````````````````````````` - - -A backslash at the end of the line is a [hard line break]: - -```````````````````````````````` example -foo\ -bar -. -

foo
-bar

-```````````````````````````````` - - -Backslash escapes do not work in code blocks, code spans, autolinks, or -raw HTML: - -```````````````````````````````` example -`` \[\` `` -. -

\[\`

-```````````````````````````````` - - -```````````````````````````````` example - \[\] -. -
\[\]
-
-```````````````````````````````` - - -```````````````````````````````` example -~~~ -\[\] -~~~ -. -
\[\]
-
-```````````````````````````````` - - -```````````````````````````````` example - -. -

http://example.com?find=\*

-```````````````````````````````` - - -```````````````````````````````` example - -. - -```````````````````````````````` - - -But they work in all other contexts, including URLs and link titles, -link references, and [info strings] in [fenced code blocks]: - -```````````````````````````````` example -[foo](/bar\* "ti\*tle") -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -[foo] - -[foo]: /bar\* "ti\*tle" -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -``` foo\+bar -foo -``` -. -
foo
-
-```````````````````````````````` - - - -## Entity and numeric character references - -All valid HTML entity references and numeric character -references, except those occuring in code blocks and code spans, -are recognized as such and treated as equivalent to the -corresponding Unicode characters. Conforming CommonMark parsers -need not store information about whether a particular character -was represented in the source using a Unicode character or -an entity reference. - -[Entity references](@) consist of `&` + any of the valid -HTML5 entity names + `;`. The -document -is used as an authoritative source for the valid entity -references and their corresponding code points. - -```````````````````````````````` example -  & © Æ Ď -¾ ℋ ⅆ -∲ ≧̸ -. -

  & © Æ Ď -¾ ℋ ⅆ -∲ ≧̸

-```````````````````````````````` - - -[Decimal numeric character -references](@) -consist of `&#` + a string of 1--8 arabic digits + `;`. A -numeric character reference is parsed as the corresponding -Unicode character. Invalid Unicode code points will be replaced by -the REPLACEMENT CHARACTER (`U+FFFD`). For security reasons, -the code point `U+0000` will also be replaced by `U+FFFD`. - -```````````````````````````````` example -# Ӓ Ϡ � � -. -

# Ӓ Ϡ � �

-```````````````````````````````` - - -[Hexadecimal numeric character -references](@) consist of `&#` + -either `X` or `x` + a string of 1-8 hexadecimal digits + `;`. -They too are parsed as the corresponding Unicode character (this -time specified with a hexadecimal numeral instead of decimal). - -```````````````````````````````` example -" ആ ಫ -. -

" ആ ಫ

-```````````````````````````````` - - -Here are some nonentities: - -```````````````````````````````` example -  &x; &#; &#x; -&ThisIsNotDefined; &hi?; -. -

&nbsp &x; &#; &#x; -&ThisIsNotDefined; &hi?;

-```````````````````````````````` - - -Although HTML5 does accept some entity references -without a trailing semicolon (such as `©`), these are not -recognized here, because it makes the grammar too ambiguous: - -```````````````````````````````` example -© -. -

&copy

-```````````````````````````````` - - -Strings that are not on the list of HTML5 named entities are not -recognized as entity references either: - -```````````````````````````````` example -&MadeUpEntity; -. -

&MadeUpEntity;

-```````````````````````````````` - - -Entity and numeric character references are recognized in any -context besides code spans or code blocks, including -URLs, [link titles], and [fenced code block][] [info strings]: - -```````````````````````````````` example - -. - -```````````````````````````````` - - -```````````````````````````````` example -[foo](/föö "föö") -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -[foo] - -[foo]: /föö "föö" -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -``` föö -foo -``` -. -
foo
-
-```````````````````````````````` - - -Entity and numeric character references are treated as literal -text in code spans and code blocks: - -```````````````````````````````` example -`föö` -. -

f&ouml;&ouml;

-```````````````````````````````` - - -```````````````````````````````` example - föfö -. -
f&ouml;f&ouml;
-
-```````````````````````````````` - - -## Code spans - -A [backtick string](@) -is a string of one or more backtick characters (`` ` ``) that is neither -preceded nor followed by a backtick. - -A [code span](@) begins with a backtick string and ends with -a backtick string of equal length. The contents of the code span are -the characters between the two backtick strings, with leading and -trailing spaces and [line endings] removed, and -[whitespace] collapsed to single spaces. - -This is a simple code span: - -```````````````````````````````` example -`foo` -. -

foo

-```````````````````````````````` - - -Here two backticks are used, because the code contains a backtick. -This example also illustrates stripping of leading and trailing spaces: - -```````````````````````````````` example -`` foo ` bar `` -. -

foo ` bar

-```````````````````````````````` - - -This example shows the motivation for stripping leading and trailing -spaces: - -```````````````````````````````` example -` `` ` -. -

``

-```````````````````````````````` - - -[Line endings] are treated like spaces: - -```````````````````````````````` example -`` -foo -`` -. -

foo

-```````````````````````````````` - - -Interior spaces and [line endings] are collapsed into -single spaces, just as they would be by a browser: - -```````````````````````````````` example -`foo bar - baz` -. -

foo bar baz

-```````````````````````````````` - - -Not all [Unicode whitespace] (for instance, non-breaking space) is -collapsed, however: - -```````````````````````````````` example -`a  b` -. -

a  b

-```````````````````````````````` - - -Q: Why not just leave the spaces, since browsers will collapse them -anyway? A: Because we might be targeting a non-HTML format, and we -shouldn't rely on HTML-specific rendering assumptions. - -(Existing implementations differ in their treatment of internal -spaces and [line endings]. Some, including `Markdown.pl` and -`showdown`, convert an internal [line ending] into a -`
` tag. But this makes things difficult for those who like to -hard-wrap their paragraphs, since a line break in the midst of a code -span will cause an unintended line break in the output. Others just -leave internal spaces as they are, which is fine if only HTML is being -targeted.) - -```````````````````````````````` example -`foo `` bar` -. -

foo `` bar

-```````````````````````````````` - - -Note that backslash escapes do not work in code spans. All backslashes -are treated literally: - -```````````````````````````````` example -`foo\`bar` -. -

foo\bar`

-```````````````````````````````` - - -Backslash escapes are never needed, because one can always choose a -string of *n* backtick characters as delimiters, where the code does -not contain any strings of exactly *n* backtick characters. - -Code span backticks have higher precedence than any other inline -constructs except HTML tags and autolinks. Thus, for example, this is -not parsed as emphasized text, since the second `*` is part of a code -span: - -```````````````````````````````` example -*foo`*` -. -

*foo*

-```````````````````````````````` - - -And this is not parsed as a link: - -```````````````````````````````` example -[not a `link](/foo`) -. -

[not a link](/foo)

-```````````````````````````````` - - -Code spans, HTML tags, and autolinks have the same precedence. -Thus, this is code: - -```````````````````````````````` example -`` -. -

<a href="">`

-```````````````````````````````` - - -But this is an HTML tag: - -```````````````````````````````` example -
` -. -

`

-```````````````````````````````` - - -And this is code: - -```````````````````````````````` example -`` -. -

<http://foo.bar.baz>`

-```````````````````````````````` - - -But this is an autolink: - -```````````````````````````````` example -` -. -

http://foo.bar.`baz`

-```````````````````````````````` - - -When a backtick string is not closed by a matching backtick string, -we just have literal backticks: - -```````````````````````````````` example -```foo`` -. -

```foo``

-```````````````````````````````` - - -```````````````````````````````` example -`foo -. -

`foo

-```````````````````````````````` - -The following case also illustrates the need for opening and -closing backtick strings to be equal in length: - -```````````````````````````````` example -`foo``bar`` -. -

`foobar

-```````````````````````````````` - - -## Emphasis and strong emphasis - -John Gruber's original [Markdown syntax -description](http://daringfireball.net/projects/markdown/syntax#em) says: - -> Markdown treats asterisks (`*`) and underscores (`_`) as indicators of -> emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML -> `` tag; double `*`'s or `_`'s will be wrapped with an HTML `` -> tag. - -This is enough for most users, but these rules leave much undecided, -especially when it comes to nested emphasis. The original -`Markdown.pl` test suite makes it clear that triple `***` and -`___` delimiters can be used for strong emphasis, and most -implementations have also allowed the following patterns: - -``` markdown -***strong emph*** -***strong** in emph* -***emph* in strong** -**in strong *emph*** -*in emph **strong*** -``` - -The following patterns are less widely supported, but the intent -is clear and they are useful (especially in contexts like bibliography -entries): - -``` markdown -*emph *with emph* in it* -**strong **with strong** in it** -``` - -Many implementations have also restricted intraword emphasis to -the `*` forms, to avoid unwanted emphasis in words containing -internal underscores. (It is best practice to put these in code -spans, but users often do not.) - -``` markdown -internal emphasis: foo*bar*baz -no emphasis: foo_bar_baz -``` - -The rules given below capture all of these patterns, while allowing -for efficient parsing strategies that do not backtrack. - -First, some definitions. A [delimiter run](@) is either -a sequence of one or more `*` characters that is not preceded or -followed by a non-backslash-escaped `*` character, or a sequence -of one or more `_` characters that is not preceded or followed by -a non-backslash-escaped `_` character. - -A [left-flanking delimiter run](@) is -a [delimiter run] that is (a) not followed by [Unicode whitespace], -and (b) not followed by a [punctuation character], or -preceded by [Unicode whitespace] or a [punctuation character]. -For purposes of this definition, the beginning and the end of -the line count as Unicode whitespace. - -A [right-flanking delimiter run](@) is -a [delimiter run] that is (a) not preceded by [Unicode whitespace], -and (b) not preceded by a [punctuation character], or -followed by [Unicode whitespace] or a [punctuation character]. -For purposes of this definition, the beginning and the end of -the line count as Unicode whitespace. - -Here are some examples of delimiter runs. - - - left-flanking but not right-flanking: - - ``` - ***abc - _abc - **"abc" - _"abc" - ``` - - - right-flanking but not left-flanking: - - ``` - abc*** - abc_ - "abc"** - "abc"_ - ``` - - - Both left and right-flanking: - - ``` - abc***def - "abc"_"def" - ``` - - - Neither left nor right-flanking: - - ``` - abc *** def - a _ b - ``` - -(The idea of distinguishing left-flanking and right-flanking -delimiter runs based on the character before and the character -after comes from Roopesh Chander's -[vfmd](http://www.vfmd.org/vfmd-spec/specification/#procedure-for-identifying-emphasis-tags). -vfmd uses the terminology "emphasis indicator string" instead of "delimiter -run," and its rules for distinguishing left- and right-flanking runs -are a bit more complex than the ones given here.) - -The following rules define emphasis and strong emphasis: - -1. A single `*` character [can open emphasis](@) - iff (if and only if) it is part of a [left-flanking delimiter run]. - -2. A single `_` character [can open emphasis] iff - it is part of a [left-flanking delimiter run] - and either (a) not part of a [right-flanking delimiter run] - or (b) part of a [right-flanking delimiter run] - preceded by punctuation. - -3. A single `*` character [can close emphasis](@) - iff it is part of a [right-flanking delimiter run]. - -4. A single `_` character [can close emphasis] iff - it is part of a [right-flanking delimiter run] - and either (a) not part of a [left-flanking delimiter run] - or (b) part of a [left-flanking delimiter run] - followed by punctuation. - -5. A double `**` [can open strong emphasis](@) - iff it is part of a [left-flanking delimiter run]. - -6. A double `__` [can open strong emphasis] iff - it is part of a [left-flanking delimiter run] - and either (a) not part of a [right-flanking delimiter run] - or (b) part of a [right-flanking delimiter run] - preceded by punctuation. - -7. A double `**` [can close strong emphasis](@) - iff it is part of a [right-flanking delimiter run]. - -8. A double `__` [can close strong emphasis] iff - it is part of a [right-flanking delimiter run] - and either (a) not part of a [left-flanking delimiter run] - or (b) part of a [left-flanking delimiter run] - followed by punctuation. - -9. Emphasis begins with a delimiter that [can open emphasis] and ends - with a delimiter that [can close emphasis], and that uses the same - character (`_` or `*`) as the opening delimiter. The - opening and closing delimiters must belong to separate - [delimiter runs]. If one of the delimiters can both - open and close emphasis, then the sum of the lengths of the - delimiter runs containing the opening and closing delimiters - must not be a multiple of 3. - -10. Strong emphasis begins with a delimiter that - [can open strong emphasis] and ends with a delimiter that - [can close strong emphasis], and that uses the same character - (`_` or `*`) as the opening delimiter. The - opening and closing delimiters must belong to separate - [delimiter runs]. If one of the delimiters can both open - and close strong emphasis, then the sum of the lengths of - the delimiter runs containing the opening and closing - delimiters must not be a multiple of 3. - -11. A literal `*` character cannot occur at the beginning or end of - `*`-delimited emphasis or `**`-delimited strong emphasis, unless it - is backslash-escaped. - -12. A literal `_` character cannot occur at the beginning or end of - `_`-delimited emphasis or `__`-delimited strong emphasis, unless it - is backslash-escaped. - -Where rules 1--12 above are compatible with multiple parsings, -the following principles resolve ambiguity: - -13. The number of nestings should be minimized. Thus, for example, - an interpretation `...` is always preferred to - `...`. - -14. An interpretation `...` is always - preferred to `...`. - -15. When two potential emphasis or strong emphasis spans overlap, - so that the second begins before the first ends and ends after - the first ends, the first takes precedence. Thus, for example, - `*foo _bar* baz_` is parsed as `foo _bar baz_` rather - than `*foo bar* baz`. - -16. When there are two potential emphasis or strong emphasis spans - with the same closing delimiter, the shorter one (the one that - opens later) takes precedence. Thus, for example, - `**foo **bar baz**` is parsed as `**foo bar baz` - rather than `foo **bar baz`. - -17. Inline code spans, links, images, and HTML tags group more tightly - than emphasis. So, when there is a choice between an interpretation - that contains one of these elements and one that does not, the - former always wins. Thus, for example, `*[foo*](bar)` is - parsed as `*foo*` rather than as - `[foo](bar)`. - -These rules can be illustrated through a series of examples. - -Rule 1: - -```````````````````````````````` example -*foo bar* -. -

foo bar

-```````````````````````````````` - - -This is not emphasis, because the opening `*` is followed by -whitespace, and hence not part of a [left-flanking delimiter run]: - -```````````````````````````````` example -a * foo bar* -. -

a * foo bar*

-```````````````````````````````` - - -This is not emphasis, because the opening `*` is preceded -by an alphanumeric and followed by punctuation, and hence -not part of a [left-flanking delimiter run]: - -```````````````````````````````` example -a*"foo"* -. -

a*"foo"*

-```````````````````````````````` - - -Unicode nonbreaking spaces count as whitespace, too: - -```````````````````````````````` example -* a * -. -

* a *

-```````````````````````````````` - - -Intraword emphasis with `*` is permitted: - -```````````````````````````````` example -foo*bar* -. -

foobar

-```````````````````````````````` - - -```````````````````````````````` example -5*6*78 -. -

5678

-```````````````````````````````` - - -Rule 2: - -```````````````````````````````` example -_foo bar_ -. -

foo bar

-```````````````````````````````` - - -This is not emphasis, because the opening `_` is followed by -whitespace: - -```````````````````````````````` example -_ foo bar_ -. -

_ foo bar_

-```````````````````````````````` - - -This is not emphasis, because the opening `_` is preceded -by an alphanumeric and followed by punctuation: - -```````````````````````````````` example -a_"foo"_ -. -

a_"foo"_

-```````````````````````````````` - - -Emphasis with `_` is not allowed inside words: - -```````````````````````````````` example -foo_bar_ -. -

foo_bar_

-```````````````````````````````` - - -```````````````````````````````` example -5_6_78 -. -

5_6_78

-```````````````````````````````` - - -```````````````````````````````` example -пристаням_стремятся_ -. -

пристаням_стремятся_

-```````````````````````````````` - - -Here `_` does not generate emphasis, because the first delimiter run -is right-flanking and the second left-flanking: - -```````````````````````````````` example -aa_"bb"_cc -. -

aa_"bb"_cc

-```````````````````````````````` - - -This is emphasis, even though the opening delimiter is -both left- and right-flanking, because it is preceded by -punctuation: - -```````````````````````````````` example -foo-_(bar)_ -. -

foo-(bar)

-```````````````````````````````` - - -Rule 3: - -This is not emphasis, because the closing delimiter does -not match the opening delimiter: - -```````````````````````````````` example -_foo* -. -

_foo*

-```````````````````````````````` - - -This is not emphasis, because the closing `*` is preceded by -whitespace: - -```````````````````````````````` example -*foo bar * -. -

*foo bar *

-```````````````````````````````` - - -A newline also counts as whitespace: - -```````````````````````````````` example -*foo bar -* -. -

*foo bar -*

-```````````````````````````````` - - -This is not emphasis, because the second `*` is -preceded by punctuation and followed by an alphanumeric -(hence it is not part of a [right-flanking delimiter run]: - -```````````````````````````````` example -*(*foo) -. -

*(*foo)

-```````````````````````````````` - - -The point of this restriction is more easily appreciated -with this example: - -```````````````````````````````` example -*(*foo*)* -. -

(foo)

-```````````````````````````````` - - -Intraword emphasis with `*` is allowed: - -```````````````````````````````` example -*foo*bar -. -

foobar

-```````````````````````````````` - - - -Rule 4: - -This is not emphasis, because the closing `_` is preceded by -whitespace: - -```````````````````````````````` example -_foo bar _ -. -

_foo bar _

-```````````````````````````````` - - -This is not emphasis, because the second `_` is -preceded by punctuation and followed by an alphanumeric: - -```````````````````````````````` example -_(_foo) -. -

_(_foo)

-```````````````````````````````` - - -This is emphasis within emphasis: - -```````````````````````````````` example -_(_foo_)_ -. -

(foo)

-```````````````````````````````` - - -Intraword emphasis is disallowed for `_`: - -```````````````````````````````` example -_foo_bar -. -

_foo_bar

-```````````````````````````````` - - -```````````````````````````````` example -_пристаням_стремятся -. -

_пристаням_стремятся

-```````````````````````````````` - - -```````````````````````````````` example -_foo_bar_baz_ -. -

foo_bar_baz

-```````````````````````````````` - - -This is emphasis, even though the closing delimiter is -both left- and right-flanking, because it is followed by -punctuation: - -```````````````````````````````` example -_(bar)_. -. -

(bar).

-```````````````````````````````` - - -Rule 5: - -```````````````````````````````` example -**foo bar** -. -

foo bar

-```````````````````````````````` - - -This is not strong emphasis, because the opening delimiter is -followed by whitespace: - -```````````````````````````````` example -** foo bar** -. -

** foo bar**

-```````````````````````````````` - - -This is not strong emphasis, because the opening `**` is preceded -by an alphanumeric and followed by punctuation, and hence -not part of a [left-flanking delimiter run]: - -```````````````````````````````` example -a**"foo"** -. -

a**"foo"**

-```````````````````````````````` - - -Intraword strong emphasis with `**` is permitted: - -```````````````````````````````` example -foo**bar** -. -

foobar

-```````````````````````````````` - - -Rule 6: - -```````````````````````````````` example -__foo bar__ -. -

foo bar

-```````````````````````````````` - - -This is not strong emphasis, because the opening delimiter is -followed by whitespace: - -```````````````````````````````` example -__ foo bar__ -. -

__ foo bar__

-```````````````````````````````` - - -A newline counts as whitespace: -```````````````````````````````` example -__ -foo bar__ -. -

__ -foo bar__

-```````````````````````````````` - - -This is not strong emphasis, because the opening `__` is preceded -by an alphanumeric and followed by punctuation: - -```````````````````````````````` example -a__"foo"__ -. -

a__"foo"__

-```````````````````````````````` - - -Intraword strong emphasis is forbidden with `__`: - -```````````````````````````````` example -foo__bar__ -. -

foo__bar__

-```````````````````````````````` - - -```````````````````````````````` example -5__6__78 -. -

5__6__78

-```````````````````````````````` - - -```````````````````````````````` example -пристаням__стремятся__ -. -

пристаням__стремятся__

-```````````````````````````````` - - -```````````````````````````````` example -__foo, __bar__, baz__ -. -

foo, bar, baz

-```````````````````````````````` - - -This is strong emphasis, even though the opening delimiter is -both left- and right-flanking, because it is preceded by -punctuation: - -```````````````````````````````` example -foo-__(bar)__ -. -

foo-(bar)

-```````````````````````````````` - - - -Rule 7: - -This is not strong emphasis, because the closing delimiter is preceded -by whitespace: - -```````````````````````````````` example -**foo bar ** -. -

**foo bar **

-```````````````````````````````` - - -(Nor can it be interpreted as an emphasized `*foo bar *`, because of -Rule 11.) - -This is not strong emphasis, because the second `**` is -preceded by punctuation and followed by an alphanumeric: - -```````````````````````````````` example -**(**foo) -. -

**(**foo)

-```````````````````````````````` - - -The point of this restriction is more easily appreciated -with these examples: - -```````````````````````````````` example -*(**foo**)* -. -

(foo)

-```````````````````````````````` - - -```````````````````````````````` example -**Gomphocarpus (*Gomphocarpus physocarpus*, syn. -*Asclepias physocarpa*)** -. -

Gomphocarpus (Gomphocarpus physocarpus, syn. -Asclepias physocarpa)

-```````````````````````````````` - - -```````````````````````````````` example -**foo "*bar*" foo** -. -

foo "bar" foo

-```````````````````````````````` - - -Intraword emphasis: - -```````````````````````````````` example -**foo**bar -. -

foobar

-```````````````````````````````` - - -Rule 8: - -This is not strong emphasis, because the closing delimiter is -preceded by whitespace: - -```````````````````````````````` example -__foo bar __ -. -

__foo bar __

-```````````````````````````````` - - -This is not strong emphasis, because the second `__` is -preceded by punctuation and followed by an alphanumeric: - -```````````````````````````````` example -__(__foo) -. -

__(__foo)

-```````````````````````````````` - - -The point of this restriction is more easily appreciated -with this example: - -```````````````````````````````` example -_(__foo__)_ -. -

(foo)

-```````````````````````````````` - - -Intraword strong emphasis is forbidden with `__`: - -```````````````````````````````` example -__foo__bar -. -

__foo__bar

-```````````````````````````````` - - -```````````````````````````````` example -__пристаням__стремятся -. -

__пристаням__стремятся

-```````````````````````````````` - - -```````````````````````````````` example -__foo__bar__baz__ -. -

foo__bar__baz

-```````````````````````````````` - - -This is strong emphasis, even though the closing delimiter is -both left- and right-flanking, because it is followed by -punctuation: - -```````````````````````````````` example -__(bar)__. -. -

(bar).

-```````````````````````````````` - - -Rule 9: - -Any nonempty sequence of inline elements can be the contents of an -emphasized span. - -```````````````````````````````` example -*foo [bar](/url)* -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -*foo -bar* -. -

foo -bar

-```````````````````````````````` - - -In particular, emphasis and strong emphasis can be nested -inside emphasis: - -```````````````````````````````` example -_foo __bar__ baz_ -. -

foo bar baz

-```````````````````````````````` - - -```````````````````````````````` example -_foo _bar_ baz_ -. -

foo bar baz

-```````````````````````````````` - - -```````````````````````````````` example -__foo_ bar_ -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -*foo *bar** -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -*foo **bar** baz* -. -

foo bar baz

-```````````````````````````````` - -```````````````````````````````` example -*foo**bar**baz* -. -

foobarbaz

-```````````````````````````````` - -Note that in the preceding case, the interpretation - -``` markdown -

foobarbaz

-``` - - -is precluded by the condition that a delimiter that -can both open and close (like the `*` after `foo`) -cannot form emphasis if the sum of the lengths of -the delimiter runs containing the opening and -closing delimiters is a multiple of 3. - -The same condition ensures that the following -cases are all strong emphasis nested inside -emphasis, even when the interior spaces are -omitted: - - -```````````````````````````````` example -***foo** bar* -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -*foo **bar*** -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -*foo**bar*** -. -

foobar

-```````````````````````````````` - - -Indefinite levels of nesting are possible: - -```````````````````````````````` example -*foo **bar *baz* bim** bop* -. -

foo bar baz bim bop

-```````````````````````````````` - - -```````````````````````````````` example -*foo [*bar*](/url)* -. -

foo bar

-```````````````````````````````` - - -There can be no empty emphasis or strong emphasis: - -```````````````````````````````` example -** is not an empty emphasis -. -

** is not an empty emphasis

-```````````````````````````````` - - -```````````````````````````````` example -**** is not an empty strong emphasis -. -

**** is not an empty strong emphasis

-```````````````````````````````` - - - -Rule 10: - -Any nonempty sequence of inline elements can be the contents of an -strongly emphasized span. - -```````````````````````````````` example -**foo [bar](/url)** -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -**foo -bar** -. -

foo -bar

-```````````````````````````````` - - -In particular, emphasis and strong emphasis can be nested -inside strong emphasis: - -```````````````````````````````` example -__foo _bar_ baz__ -. -

foo bar baz

-```````````````````````````````` - - -```````````````````````````````` example -__foo __bar__ baz__ -. -

foo bar baz

-```````````````````````````````` - - -```````````````````````````````` example -____foo__ bar__ -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -**foo **bar**** -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -**foo *bar* baz** -. -

foo bar baz

-```````````````````````````````` - - -```````````````````````````````` example -**foo*bar*baz** -. -

foobarbaz

-```````````````````````````````` - - -```````````````````````````````` example -***foo* bar** -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -**foo *bar*** -. -

foo bar

-```````````````````````````````` - - -Indefinite levels of nesting are possible: - -```````````````````````````````` example -**foo *bar **baz** -bim* bop** -. -

foo bar baz -bim bop

-```````````````````````````````` - - -```````````````````````````````` example -**foo [*bar*](/url)** -. -

foo bar

-```````````````````````````````` - - -There can be no empty emphasis or strong emphasis: - -```````````````````````````````` example -__ is not an empty emphasis -. -

__ is not an empty emphasis

-```````````````````````````````` - - -```````````````````````````````` example -____ is not an empty strong emphasis -. -

____ is not an empty strong emphasis

-```````````````````````````````` - - - -Rule 11: - -```````````````````````````````` example -foo *** -. -

foo ***

-```````````````````````````````` - - -```````````````````````````````` example -foo *\** -. -

foo *

-```````````````````````````````` - - -```````````````````````````````` example -foo *_* -. -

foo _

-```````````````````````````````` - - -```````````````````````````````` example -foo ***** -. -

foo *****

-```````````````````````````````` - - -```````````````````````````````` example -foo **\*** -. -

foo *

-```````````````````````````````` - - -```````````````````````````````` example -foo **_** -. -

foo _

-```````````````````````````````` - - -Note that when delimiters do not match evenly, Rule 11 determines -that the excess literal `*` characters will appear outside of the -emphasis, rather than inside it: - -```````````````````````````````` example -**foo* -. -

*foo

-```````````````````````````````` - - -```````````````````````````````` example -*foo** -. -

foo*

-```````````````````````````````` - - -```````````````````````````````` example -***foo** -. -

*foo

-```````````````````````````````` - - -```````````````````````````````` example -****foo* -. -

***foo

-```````````````````````````````` - - -```````````````````````````````` example -**foo*** -. -

foo*

-```````````````````````````````` - - -```````````````````````````````` example -*foo**** -. -

foo***

-```````````````````````````````` - - - -Rule 12: - -```````````````````````````````` example -foo ___ -. -

foo ___

-```````````````````````````````` - - -```````````````````````````````` example -foo _\__ -. -

foo _

-```````````````````````````````` - - -```````````````````````````````` example -foo _*_ -. -

foo *

-```````````````````````````````` - - -```````````````````````````````` example -foo _____ -. -

foo _____

-```````````````````````````````` - - -```````````````````````````````` example -foo __\___ -. -

foo _

-```````````````````````````````` - - -```````````````````````````````` example -foo __*__ -. -

foo *

-```````````````````````````````` - - -```````````````````````````````` example -__foo_ -. -

_foo

-```````````````````````````````` - - -Note that when delimiters do not match evenly, Rule 12 determines -that the excess literal `_` characters will appear outside of the -emphasis, rather than inside it: - -```````````````````````````````` example -_foo__ -. -

foo_

-```````````````````````````````` - - -```````````````````````````````` example -___foo__ -. -

_foo

-```````````````````````````````` - - -```````````````````````````````` example -____foo_ -. -

___foo

-```````````````````````````````` - - -```````````````````````````````` example -__foo___ -. -

foo_

-```````````````````````````````` - - -```````````````````````````````` example -_foo____ -. -

foo___

-```````````````````````````````` - - -Rule 13 implies that if you want emphasis nested directly inside -emphasis, you must use different delimiters: - -```````````````````````````````` example -**foo** -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -*_foo_* -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -__foo__ -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -_*foo*_ -. -

foo

-```````````````````````````````` - - -However, strong emphasis within strong emphasis is possible without -switching delimiters: - -```````````````````````````````` example -****foo**** -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -____foo____ -. -

foo

-```````````````````````````````` - - - -Rule 13 can be applied to arbitrarily long sequences of -delimiters: - -```````````````````````````````` example -******foo****** -. -

foo

-```````````````````````````````` - - -Rule 14: - -```````````````````````````````` example -***foo*** -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -_____foo_____ -. -

foo

-```````````````````````````````` - - -Rule 15: - -```````````````````````````````` example -*foo _bar* baz_ -. -

foo _bar baz_

-```````````````````````````````` - - -```````````````````````````````` example -*foo __bar *baz bim__ bam* -. -

foo bar *baz bim bam

-```````````````````````````````` - - -Rule 16: - -```````````````````````````````` example -**foo **bar baz** -. -

**foo bar baz

-```````````````````````````````` - - -```````````````````````````````` example -*foo *bar baz* -. -

*foo bar baz

-```````````````````````````````` - - -Rule 17: - -```````````````````````````````` example -*[bar*](/url) -. -

*bar*

-```````````````````````````````` - - -```````````````````````````````` example -_foo [bar_](/url) -. -

_foo bar_

-```````````````````````````````` - - -```````````````````````````````` example -* -. -

*

-```````````````````````````````` - - -```````````````````````````````` example -** -. -

**

-```````````````````````````````` - - -```````````````````````````````` example -__ -. -

__

-```````````````````````````````` - - -```````````````````````````````` example -*a `*`* -. -

a *

-```````````````````````````````` - - -```````````````````````````````` example -_a `_`_ -. -

a _

-```````````````````````````````` - - -```````````````````````````````` example -**a -. -

**ahttp://foo.bar/?q=**

-```````````````````````````````` - - -```````````````````````````````` example -__a -. -

__ahttp://foo.bar/?q=__

-```````````````````````````````` - - - -## Links - -A link contains [link text] (the visible text), a [link destination] -(the URI that is the link destination), and optionally a [link title]. -There are two basic kinds of links in Markdown. In [inline links] the -destination and title are given immediately after the link text. In -[reference links] the destination and title are defined elsewhere in -the document. - -A [link text](@) consists of a sequence of zero or more -inline elements enclosed by square brackets (`[` and `]`). The -following rules apply: - -- Links may not contain other links, at any level of nesting. If - multiple otherwise valid link definitions appear nested inside each - other, the inner-most definition is used. - -- Brackets are allowed in the [link text] only if (a) they - are backslash-escaped or (b) they appear as a matched pair of brackets, - with an open bracket `[`, a sequence of zero or more inlines, and - a close bracket `]`. - -- Backtick [code spans], [autolinks], and raw [HTML tags] bind more tightly - than the brackets in link text. Thus, for example, - `` [foo`]` `` could not be a link text, since the second `]` - is part of a code span. - -- The brackets in link text bind more tightly than markers for - [emphasis and strong emphasis]. Thus, for example, `*[foo*](url)` is a link. - -A [link destination](@) consists of either - -- a sequence of zero or more characters between an opening `<` and a - closing `>` that contains no spaces, line breaks, or unescaped - `<` or `>` characters, or - -- a nonempty sequence of characters that does not include - ASCII space or control characters, and includes parentheses - only if (a) they are backslash-escaped or (b) they are part of - a balanced pair of unescaped parentheses. (Implementations - may impose limits on parentheses nesting to avoid performance - issues, but at least three levels of nesting should be supported.) - -A [link title](@) consists of either - -- a sequence of zero or more characters between straight double-quote - characters (`"`), including a `"` character only if it is - backslash-escaped, or - -- a sequence of zero or more characters between straight single-quote - characters (`'`), including a `'` character only if it is - backslash-escaped, or - -- a sequence of zero or more characters between matching parentheses - (`(...)`), including a `)` character only if it is backslash-escaped. - -Although [link titles] may span multiple lines, they may not contain -a [blank line]. - -An [inline link](@) consists of a [link text] followed immediately -by a left parenthesis `(`, optional [whitespace], an optional -[link destination], an optional [link title] separated from the link -destination by [whitespace], optional [whitespace], and a right -parenthesis `)`. The link's text consists of the inlines contained -in the [link text] (excluding the enclosing square brackets). -The link's URI consists of the link destination, excluding enclosing -`<...>` if present, with backslash-escapes in effect as described -above. The link's title consists of the link title, excluding its -enclosing delimiters, with backslash-escapes in effect as described -above. - -Here is a simple inline link: - -```````````````````````````````` example -[link](/uri "title") -. -

link

-```````````````````````````````` - - -The title may be omitted: - -```````````````````````````````` example -[link](/uri) -. -

link

-```````````````````````````````` - - -Both the title and the destination may be omitted: - -```````````````````````````````` example -[link]() -. -

link

-```````````````````````````````` - - -```````````````````````````````` example -[link](<>) -. -

link

-```````````````````````````````` - - -The destination cannot contain spaces or line breaks, -even if enclosed in pointy brackets: - -```````````````````````````````` example -[link](/my uri) -. -

[link](/my uri)

-```````````````````````````````` - - -```````````````````````````````` example -[link]() -. -

[link](</my uri>)

-```````````````````````````````` - - -```````````````````````````````` example -[link](foo -bar) -. -

[link](foo -bar)

-```````````````````````````````` - - -```````````````````````````````` example -[link]() -. -

[link]()

-```````````````````````````````` - -Parentheses inside the link destination may be escaped: - -```````````````````````````````` example -[link](\(foo\)) -. -

link

-```````````````````````````````` - -Any number of parentheses are allowed without escaping, as long as they are -balanced: - -```````````````````````````````` example -[link](foo(and(bar))) -. -

link

-```````````````````````````````` - -However, if you have unbalanced parentheses, you need to escape or use the -`<...>` form: - -```````````````````````````````` example -[link](foo\(and\(bar\)) -. -

link

-```````````````````````````````` - - -```````````````````````````````` example -[link]() -. -

link

-```````````````````````````````` - - -Parentheses and other symbols can also be escaped, as usual -in Markdown: - -```````````````````````````````` example -[link](foo\)\:) -. -

link

-```````````````````````````````` - - -A link can contain fragment identifiers and queries: - -```````````````````````````````` example -[link](#fragment) - -[link](http://example.com#fragment) - -[link](http://example.com?foo=3#frag) -. -

link

-

link

-

link

-```````````````````````````````` - - -Note that a backslash before a non-escapable character is -just a backslash: - -```````````````````````````````` example -[link](foo\bar) -. -

link

-```````````````````````````````` - - -URL-escaping should be left alone inside the destination, as all -URL-escaped characters are also valid URL characters. Entity and -numerical character references in the destination will be parsed -into the corresponding Unicode code points, as usual. These may -be optionally URL-escaped when written as HTML, but this spec -does not enforce any particular policy for rendering URLs in -HTML or other formats. Renderers may make different decisions -about how to escape or normalize URLs in the output. - -```````````````````````````````` example -[link](foo%20bä) -. -

link

-```````````````````````````````` - - -Note that, because titles can often be parsed as destinations, -if you try to omit the destination and keep the title, you'll -get unexpected results: - -```````````````````````````````` example -[link]("title") -. -

link

-```````````````````````````````` - - -Titles may be in single quotes, double quotes, or parentheses: - -```````````````````````````````` example -[link](/url "title") -[link](/url 'title') -[link](/url (title)) -. -

link -link -link

-```````````````````````````````` - - -Backslash escapes and entity and numeric character references -may be used in titles: - -```````````````````````````````` example -[link](/url "title \""") -. -

link

-```````````````````````````````` - - -Titles must be separated from the link using a [whitespace]. -Other [Unicode whitespace] like non-breaking space doesn't work. - -```````````````````````````````` example -[link](/url "title") -. -

link

-```````````````````````````````` - - -Nested balanced quotes are not allowed without escaping: - -```````````````````````````````` example -[link](/url "title "and" title") -. -

[link](/url "title "and" title")

-```````````````````````````````` - - -But it is easy to work around this by using a different quote type: - -```````````````````````````````` example -[link](/url 'title "and" title') -. -

link

-```````````````````````````````` - - -(Note: `Markdown.pl` did allow double quotes inside a double-quoted -title, and its test suite included a test demonstrating this. -But it is hard to see a good rationale for the extra complexity this -brings, since there are already many ways---backslash escaping, -entity and numeric character references, or using a different -quote type for the enclosing title---to write titles containing -double quotes. `Markdown.pl`'s handling of titles has a number -of other strange features. For example, it allows single-quoted -titles in inline links, but not reference links. And, in -reference links but not inline links, it allows a title to begin -with `"` and end with `)`. `Markdown.pl` 1.0.1 even allows -titles with no closing quotation mark, though 1.0.2b8 does not. -It seems preferable to adopt a simple, rational rule that works -the same way in inline links and link reference definitions.) - -[Whitespace] is allowed around the destination and title: - -```````````````````````````````` example -[link]( /uri - "title" ) -. -

link

-```````````````````````````````` - - -But it is not allowed between the link text and the -following parenthesis: - -```````````````````````````````` example -[link] (/uri) -. -

[link] (/uri)

-```````````````````````````````` - - -The link text may contain balanced brackets, but not unbalanced ones, -unless they are escaped: - -```````````````````````````````` example -[link [foo [bar]]](/uri) -. -

link [foo [bar]]

-```````````````````````````````` - - -```````````````````````````````` example -[link] bar](/uri) -. -

[link] bar](/uri)

-```````````````````````````````` - - -```````````````````````````````` example -[link [bar](/uri) -. -

[link bar

-```````````````````````````````` - - -```````````````````````````````` example -[link \[bar](/uri) -. -

link [bar

-```````````````````````````````` - - -The link text may contain inline content: - -```````````````````````````````` example -[link *foo **bar** `#`*](/uri) -. -

link foo bar #

-```````````````````````````````` - - -```````````````````````````````` example -[![moon](moon.jpg)](/uri) -. -

moon

-```````````````````````````````` - - -However, links may not contain other links, at any level of nesting. - -```````````````````````````````` example -[foo [bar](/uri)](/uri) -. -

[foo bar](/uri)

-```````````````````````````````` - - -```````````````````````````````` example -[foo *[bar [baz](/uri)](/uri)*](/uri) -. -

[foo [bar baz](/uri)](/uri)

-```````````````````````````````` - - -```````````````````````````````` example -![[[foo](uri1)](uri2)](uri3) -. -

[foo](uri2)

-```````````````````````````````` - - -These cases illustrate the precedence of link text grouping over -emphasis grouping: - -```````````````````````````````` example -*[foo*](/uri) -. -

*foo*

-```````````````````````````````` - - -```````````````````````````````` example -[foo *bar](baz*) -. -

foo *bar

-```````````````````````````````` - - -Note that brackets that *aren't* part of links do not take -precedence: - -```````````````````````````````` example -*foo [bar* baz] -. -

foo [bar baz]

-```````````````````````````````` - - -These cases illustrate the precedence of HTML tags, code spans, -and autolinks over link grouping: - -```````````````````````````````` example -[foo -. -

[foo

-```````````````````````````````` - - -```````````````````````````````` example -[foo`](/uri)` -. -

[foo](/uri)

-```````````````````````````````` - - -```````````````````````````````` example -[foo -. -

[foohttp://example.com/?search=](uri)

-```````````````````````````````` - - -There are three kinds of [reference link](@)s: -[full](#full-reference-link), [collapsed](#collapsed-reference-link), -and [shortcut](#shortcut-reference-link). - -A [full reference link](@) -consists of a [link text] immediately followed by a [link label] -that [matches] a [link reference definition] elsewhere in the document. - -A [link label](@) begins with a left bracket (`[`) and ends -with the first right bracket (`]`) that is not backslash-escaped. -Between these brackets there must be at least one [non-whitespace character]. -Unescaped square bracket characters are not allowed inside the -opening and closing square brackets of [link labels]. A link -label can have at most 999 characters inside the square -brackets. - -One label [matches](@) -another just in case their normalized forms are equal. To normalize a -label, strip off the opening and closing brackets, -perform the *Unicode case fold*, strip leading and trailing -[whitespace] and collapse consecutive internal -[whitespace] to a single space. If there are multiple -matching reference link definitions, the one that comes first in the -document is used. (It is desirable in such cases to emit a warning.) - -The contents of the first link label are parsed as inlines, which are -used as the link's text. The link's URI and title are provided by the -matching [link reference definition]. - -Here is a simple example: - -```````````````````````````````` example -[foo][bar] - -[bar]: /url "title" -. -

foo

-```````````````````````````````` - - -The rules for the [link text] are the same as with -[inline links]. Thus: - -The link text may contain balanced brackets, but not unbalanced ones, -unless they are escaped: - -```````````````````````````````` example -[link [foo [bar]]][ref] - -[ref]: /uri -. -

link [foo [bar]]

-```````````````````````````````` - - -```````````````````````````````` example -[link \[bar][ref] - -[ref]: /uri -. -

link [bar

-```````````````````````````````` - - -The link text may contain inline content: - -```````````````````````````````` example -[link *foo **bar** `#`*][ref] - -[ref]: /uri -. -

link foo bar #

-```````````````````````````````` - - -```````````````````````````````` example -[![moon](moon.jpg)][ref] - -[ref]: /uri -. -

moon

-```````````````````````````````` - - -However, links may not contain other links, at any level of nesting. - -```````````````````````````````` example -[foo [bar](/uri)][ref] - -[ref]: /uri -. -

[foo bar]ref

-```````````````````````````````` - - -```````````````````````````````` example -[foo *bar [baz][ref]*][ref] - -[ref]: /uri -. -

[foo bar baz]ref

-```````````````````````````````` - - -(In the examples above, we have two [shortcut reference links] -instead of one [full reference link].) - -The following cases illustrate the precedence of link text grouping over -emphasis grouping: - -```````````````````````````````` example -*[foo*][ref] - -[ref]: /uri -. -

*foo*

-```````````````````````````````` - - -```````````````````````````````` example -[foo *bar][ref] - -[ref]: /uri -. -

foo *bar

-```````````````````````````````` - - -These cases illustrate the precedence of HTML tags, code spans, -and autolinks over link grouping: - -```````````````````````````````` example -[foo - -[ref]: /uri -. -

[foo

-```````````````````````````````` - - -```````````````````````````````` example -[foo`][ref]` - -[ref]: /uri -. -

[foo][ref]

-```````````````````````````````` - - -```````````````````````````````` example -[foo - -[ref]: /uri -. -

[foohttp://example.com/?search=][ref]

-```````````````````````````````` - - -Matching is case-insensitive: - -```````````````````````````````` example -[foo][BaR] - -[bar]: /url "title" -. -

foo

-```````````````````````````````` - - -Unicode case fold is used: - -```````````````````````````````` example -[Толпой][Толпой] is a Russian word. - -[ТОЛПОЙ]: /url -. -

Толпой is a Russian word.

-```````````````````````````````` - - -Consecutive internal [whitespace] is treated as one space for -purposes of determining matching: - -```````````````````````````````` example -[Foo - bar]: /url - -[Baz][Foo bar] -. -

Baz

-```````````````````````````````` - - -No [whitespace] is allowed between the [link text] and the -[link label]: - -```````````````````````````````` example -[foo] [bar] - -[bar]: /url "title" -. -

[foo] bar

-```````````````````````````````` - - -```````````````````````````````` example -[foo] -[bar] - -[bar]: /url "title" -. -

[foo] -bar

-```````````````````````````````` - - -This is a departure from John Gruber's original Markdown syntax -description, which explicitly allows whitespace between the link -text and the link label. It brings reference links in line with -[inline links], which (according to both original Markdown and -this spec) cannot have whitespace after the link text. More -importantly, it prevents inadvertent capture of consecutive -[shortcut reference links]. If whitespace is allowed between the -link text and the link label, then in the following we will have -a single reference link, not two shortcut reference links, as -intended: - -``` markdown -[foo] -[bar] - -[foo]: /url1 -[bar]: /url2 -``` - -(Note that [shortcut reference links] were introduced by Gruber -himself in a beta version of `Markdown.pl`, but never included -in the official syntax description. Without shortcut reference -links, it is harmless to allow space between the link text and -link label; but once shortcut references are introduced, it is -too dangerous to allow this, as it frequently leads to -unintended results.) - -When there are multiple matching [link reference definitions], -the first is used: - -```````````````````````````````` example -[foo]: /url1 - -[foo]: /url2 - -[bar][foo] -. -

bar

-```````````````````````````````` - - -Note that matching is performed on normalized strings, not parsed -inline content. So the following does not match, even though the -labels define equivalent inline content: - -```````````````````````````````` example -[bar][foo\!] - -[foo!]: /url -. -

[bar][foo!]

-```````````````````````````````` - - -[Link labels] cannot contain brackets, unless they are -backslash-escaped: - -```````````````````````````````` example -[foo][ref[] - -[ref[]: /uri -. -

[foo][ref[]

-

[ref[]: /uri

-```````````````````````````````` - - -```````````````````````````````` example -[foo][ref[bar]] - -[ref[bar]]: /uri -. -

[foo][ref[bar]]

-

[ref[bar]]: /uri

-```````````````````````````````` - - -```````````````````````````````` example -[[[foo]]] - -[[[foo]]]: /url -. -

[[[foo]]]

-

[[[foo]]]: /url

-```````````````````````````````` - - -```````````````````````````````` example -[foo][ref\[] - -[ref\[]: /uri -. -

foo

-```````````````````````````````` - - -Note that in this example `]` is not backslash-escaped: - -```````````````````````````````` example -[bar\\]: /uri - -[bar\\] -. -

bar\

-```````````````````````````````` - - -A [link label] must contain at least one [non-whitespace character]: - -```````````````````````````````` example -[] - -[]: /uri -. -

[]

-

[]: /uri

-```````````````````````````````` - - -```````````````````````````````` example -[ - ] - -[ - ]: /uri -. -

[ -]

-

[ -]: /uri

-```````````````````````````````` - - -A [collapsed reference link](@) -consists of a [link label] that [matches] a -[link reference definition] elsewhere in the -document, followed by the string `[]`. -The contents of the first link label are parsed as inlines, -which are used as the link's text. The link's URI and title are -provided by the matching reference link definition. Thus, -`[foo][]` is equivalent to `[foo][foo]`. - -```````````````````````````````` example -[foo][] - -[foo]: /url "title" -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -[*foo* bar][] - -[*foo* bar]: /url "title" -. -

foo bar

-```````````````````````````````` - - -The link labels are case-insensitive: - -```````````````````````````````` example -[Foo][] - -[foo]: /url "title" -. -

Foo

-```````````````````````````````` - - - -As with full reference links, [whitespace] is not -allowed between the two sets of brackets: - -```````````````````````````````` example -[foo] -[] - -[foo]: /url "title" -. -

foo -[]

-```````````````````````````````` - - -A [shortcut reference link](@) -consists of a [link label] that [matches] a -[link reference definition] elsewhere in the -document and is not followed by `[]` or a link label. -The contents of the first link label are parsed as inlines, -which are used as the link's text. The link's URI and title -are provided by the matching link reference definition. -Thus, `[foo]` is equivalent to `[foo][]`. - -```````````````````````````````` example -[foo] - -[foo]: /url "title" -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -[*foo* bar] - -[*foo* bar]: /url "title" -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -[[*foo* bar]] - -[*foo* bar]: /url "title" -. -

[foo bar]

-```````````````````````````````` - - -```````````````````````````````` example -[[bar [foo] - -[foo]: /url -. -

[[bar foo

-```````````````````````````````` - - -The link labels are case-insensitive: - -```````````````````````````````` example -[Foo] - -[foo]: /url "title" -. -

Foo

-```````````````````````````````` - - -A space after the link text should be preserved: - -```````````````````````````````` example -[foo] bar - -[foo]: /url -. -

foo bar

-```````````````````````````````` - - -If you just want bracketed text, you can backslash-escape the -opening bracket to avoid links: - -```````````````````````````````` example -\[foo] - -[foo]: /url "title" -. -

[foo]

-```````````````````````````````` - - -Note that this is a link, because a link label ends with the first -following closing bracket: - -```````````````````````````````` example -[foo*]: /url - -*[foo*] -. -

*foo*

-```````````````````````````````` - - -Full and compact references take precedence over shortcut -references: - -```````````````````````````````` example -[foo][bar] - -[foo]: /url1 -[bar]: /url2 -. -

foo

-```````````````````````````````` - -```````````````````````````````` example -[foo][] - -[foo]: /url1 -. -

foo

-```````````````````````````````` - -Inline links also take precedence: - -```````````````````````````````` example -[foo]() - -[foo]: /url1 -. -

foo

-```````````````````````````````` - -```````````````````````````````` example -[foo](not a link) - -[foo]: /url1 -. -

foo(not a link)

-```````````````````````````````` - -In the following case `[bar][baz]` is parsed as a reference, -`[foo]` as normal text: - -```````````````````````````````` example -[foo][bar][baz] - -[baz]: /url -. -

[foo]bar

-```````````````````````````````` - - -Here, though, `[foo][bar]` is parsed as a reference, since -`[bar]` is defined: - -```````````````````````````````` example -[foo][bar][baz] - -[baz]: /url1 -[bar]: /url2 -. -

foobaz

-```````````````````````````````` - - -Here `[foo]` is not parsed as a shortcut reference, because it -is followed by a link label (even though `[bar]` is not defined): - -```````````````````````````````` example -[foo][bar][baz] - -[baz]: /url1 -[foo]: /url2 -. -

[foo]bar

-```````````````````````````````` - - - -## Images - -Syntax for images is like the syntax for links, with one -difference. Instead of [link text], we have an -[image description](@). The rules for this are the -same as for [link text], except that (a) an -image description starts with `![` rather than `[`, and -(b) an image description may contain links. -An image description has inline elements -as its contents. When an image is rendered to HTML, -this is standardly used as the image's `alt` attribute. - -```````````````````````````````` example -![foo](/url "title") -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -![foo *bar*] - -[foo *bar*]: train.jpg "train & tracks" -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -![foo ![bar](/url)](/url2) -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -![foo [bar](/url)](/url2) -. -

foo bar

-```````````````````````````````` - - -Though this spec is concerned with parsing, not rendering, it is -recommended that in rendering to HTML, only the plain string content -of the [image description] be used. Note that in -the above example, the alt attribute's value is `foo bar`, not `foo -[bar](/url)` or `foo bar`. Only the plain string -content is rendered, without formatting. - -```````````````````````````````` example -![foo *bar*][] - -[foo *bar*]: train.jpg "train & tracks" -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -![foo *bar*][foobar] - -[FOOBAR]: train.jpg "train & tracks" -. -

foo bar

-```````````````````````````````` - - -```````````````````````````````` example -![foo](train.jpg) -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -My ![foo bar](/path/to/train.jpg "title" ) -. -

My foo bar

-```````````````````````````````` - - -```````````````````````````````` example -![foo]() -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -![](/url) -. -

-```````````````````````````````` - - -Reference-style: - -```````````````````````````````` example -![foo][bar] - -[bar]: /url -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -![foo][bar] - -[BAR]: /url -. -

foo

-```````````````````````````````` - - -Collapsed: - -```````````````````````````````` example -![foo][] - -[foo]: /url "title" -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -![*foo* bar][] - -[*foo* bar]: /url "title" -. -

foo bar

-```````````````````````````````` - - -The labels are case-insensitive: - -```````````````````````````````` example -![Foo][] - -[foo]: /url "title" -. -

Foo

-```````````````````````````````` - - -As with reference links, [whitespace] is not allowed -between the two sets of brackets: - -```````````````````````````````` example -![foo] -[] - -[foo]: /url "title" -. -

foo -[]

-```````````````````````````````` - - -Shortcut: - -```````````````````````````````` example -![foo] - -[foo]: /url "title" -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -![*foo* bar] - -[*foo* bar]: /url "title" -. -

foo bar

-```````````````````````````````` - - -Note that link labels cannot contain unescaped brackets: - -```````````````````````````````` example -![[foo]] - -[[foo]]: /url "title" -. -

![[foo]]

-

[[foo]]: /url "title"

-```````````````````````````````` - - -The link labels are case-insensitive: - -```````````````````````````````` example -![Foo] - -[foo]: /url "title" -. -

Foo

-```````````````````````````````` - - -If you just want a literal `!` followed by bracketed text, you can -backslash-escape the opening `[`: - -```````````````````````````````` example -!\[foo] - -[foo]: /url "title" -. -

![foo]

-```````````````````````````````` - - -If you want a link after a literal `!`, backslash-escape the -`!`: - -```````````````````````````````` example -\![foo] - -[foo]: /url "title" -. -

!foo

-```````````````````````````````` - - -## Autolinks - -[Autolink](@)s are absolute URIs and email addresses inside -`<` and `>`. They are parsed as links, with the URL or email address -as the link label. - -A [URI autolink](@) consists of `<`, followed by an -[absolute URI] not containing `<`, followed by `>`. It is parsed as -a link to the URI, with the URI as the link's label. - -An [absolute URI](@), -for these purposes, consists of a [scheme] followed by a colon (`:`) -followed by zero or more characters other than ASCII -[whitespace] and control characters, `<`, and `>`. If -the URI includes these characters, they must be percent-encoded -(e.g. `%20` for a space). - -For purposes of this spec, a [scheme](@) is any sequence -of 2--32 characters beginning with an ASCII letter and followed -by any combination of ASCII letters, digits, or the symbols plus -("+"), period ("."), or hyphen ("-"). - -Here are some valid autolinks: - -```````````````````````````````` example - -. -

http://foo.bar.baz

-```````````````````````````````` - - -```````````````````````````````` example - -. -

http://foo.bar.baz/test?q=hello&id=22&boolean

-```````````````````````````````` - - -```````````````````````````````` example - -. -

irc://foo.bar:2233/baz

-```````````````````````````````` - - -Uppercase is also fine: - -```````````````````````````````` example - -. -

MAILTO:FOO@BAR.BAZ

-```````````````````````````````` - - -Note that many strings that count as [absolute URIs] for -purposes of this spec are not valid URIs, because their -schemes are not registered or because of other problems -with their syntax: - -```````````````````````````````` example - -. -

a+b+c:d

-```````````````````````````````` - - -```````````````````````````````` example - -. -

made-up-scheme://foo,bar

-```````````````````````````````` - - -```````````````````````````````` example - -. -

http://../

-```````````````````````````````` - - -```````````````````````````````` example - -. -

localhost:5001/foo

-```````````````````````````````` - - -Spaces are not allowed in autolinks: - -```````````````````````````````` example - -. -

<http://foo.bar/baz bim>

-```````````````````````````````` - - -Backslash-escapes do not work inside autolinks: - -```````````````````````````````` example - -. -

http://example.com/\[\

-```````````````````````````````` - - -An [email autolink](@) -consists of `<`, followed by an [email address], -followed by `>`. The link's label is the email address, -and the URL is `mailto:` followed by the email address. - -An [email address](@), -for these purposes, is anything that matches -the [non-normative regex from the HTML5 -spec](https://html.spec.whatwg.org/multipage/forms.html#e-mail-state-(type=email)): - - /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? - (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ - -Examples of email autolinks: - -```````````````````````````````` example - -. -

foo@bar.example.com

-```````````````````````````````` - - -```````````````````````````````` example - -. -

foo+special@Bar.baz-bar0.com

-```````````````````````````````` - - -Backslash-escapes do not work inside email autolinks: - -```````````````````````````````` example - -. -

<foo+@bar.example.com>

-```````````````````````````````` - - -These are not autolinks: - -```````````````````````````````` example -<> -. -

<>

-```````````````````````````````` - - -```````````````````````````````` example -< http://foo.bar > -. -

< http://foo.bar >

-```````````````````````````````` - - -```````````````````````````````` example - -. -

<m:abc>

-```````````````````````````````` - - -```````````````````````````````` example - -. -

<foo.bar.baz>

-```````````````````````````````` - - -```````````````````````````````` example -http://example.com -. -

http://example.com

-```````````````````````````````` - - -```````````````````````````````` example -foo@bar.example.com -. -

foo@bar.example.com

-```````````````````````````````` - - -## Raw HTML - -Text between `<` and `>` that looks like an HTML tag is parsed as a -raw HTML tag and will be rendered in HTML without escaping. -Tag and attribute names are not limited to current HTML tags, -so custom tags (and even, say, DocBook tags) may be used. - -Here is the grammar for tags: - -A [tag name](@) consists of an ASCII letter -followed by zero or more ASCII letters, digits, or -hyphens (`-`). - -An [attribute](@) consists of [whitespace], -an [attribute name], and an optional -[attribute value specification]. - -An [attribute name](@) -consists of an ASCII letter, `_`, or `:`, followed by zero or more ASCII -letters, digits, `_`, `.`, `:`, or `-`. (Note: This is the XML -specification restricted to ASCII. HTML5 is laxer.) - -An [attribute value specification](@) -consists of optional [whitespace], -a `=` character, optional [whitespace], and an [attribute -value]. - -An [attribute value](@) -consists of an [unquoted attribute value], -a [single-quoted attribute value], or a [double-quoted attribute value]. - -An [unquoted attribute value](@) -is a nonempty string of characters not -including spaces, `"`, `'`, `=`, `<`, `>`, or `` ` ``. - -A [single-quoted attribute value](@) -consists of `'`, zero or more -characters not including `'`, and a final `'`. - -A [double-quoted attribute value](@) -consists of `"`, zero or more -characters not including `"`, and a final `"`. - -An [open tag](@) consists of a `<` character, a [tag name], -zero or more [attributes], optional [whitespace], an optional `/` -character, and a `>` character. - -A [closing tag](@) consists of the string ``. - -An [HTML comment](@) consists of ``, -where *text* does not start with `>` or `->`, does not end with `-`, -and does not contain `--`. (See the -[HTML5 spec](http://www.w3.org/TR/html5/syntax.html#comments).) - -A [processing instruction](@) -consists of the string ``, and the string -`?>`. - -A [declaration](@) consists of the -string ``, and the character `>`. - -A [CDATA section](@) consists of -the string ``, and the string `]]>`. - -An [HTML tag](@) consists of an [open tag], a [closing tag], -an [HTML comment], a [processing instruction], a [declaration], -or a [CDATA section]. - -Here are some simple open tags: - -```````````````````````````````` example - -. -

-```````````````````````````````` - - -Empty elements: - -```````````````````````````````` example - -. -

-```````````````````````````````` - - -[Whitespace] is allowed: - -```````````````````````````````` example - -. -

-```````````````````````````````` - - -With attributes: - -```````````````````````````````` example - -. -

-```````````````````````````````` - - -Custom tag names can be used: - -```````````````````````````````` example -Foo -. -

Foo

-```````````````````````````````` - - -Illegal tag names, not parsed as HTML: - -```````````````````````````````` example -<33> <__> -. -

<33> <__>

-```````````````````````````````` - - -Illegal attribute names: - -```````````````````````````````` example -
-. -

<a h*#ref="hi">

-```````````````````````````````` - - -Illegal attribute values: - -```````````````````````````````` example -
-. -

</a href="foo">

-```````````````````````````````` - - -Comments: - -```````````````````````````````` example -foo -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -foo -. -

foo <!-- not a comment -- two hyphens -->

-```````````````````````````````` - - -Not comments: - -```````````````````````````````` example -foo foo --> - -foo -. -

foo <!--> foo -->

-

foo <!-- foo--->

-```````````````````````````````` - - -Processing instructions: - -```````````````````````````````` example -foo -. -

foo

-```````````````````````````````` - - -Declarations: - -```````````````````````````````` example -foo -. -

foo

-```````````````````````````````` - - -CDATA sections: - -```````````````````````````````` example -foo &<]]> -. -

foo &<]]>

-```````````````````````````````` - - -Entity and numeric character references are preserved in HTML -attributes: - -```````````````````````````````` example -foo
-. -

foo

-```````````````````````````````` - - -Backslash escapes do not work in HTML attributes: - -```````````````````````````````` example -foo -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example - -. -

<a href=""">

-```````````````````````````````` - - -## Hard line breaks - -A line break (not in a code span or HTML tag) that is preceded -by two or more spaces and does not occur at the end of a block -is parsed as a [hard line break](@) (rendered -in HTML as a `
` tag): - -```````````````````````````````` example -foo -baz -. -

foo
-baz

-```````````````````````````````` - - -For a more visible alternative, a backslash before the -[line ending] may be used instead of two spaces: - -```````````````````````````````` example -foo\ -baz -. -

foo
-baz

-```````````````````````````````` - - -More than two spaces can be used: - -```````````````````````````````` example -foo -baz -. -

foo
-baz

-```````````````````````````````` - - -Leading spaces at the beginning of the next line are ignored: - -```````````````````````````````` example -foo - bar -. -

foo
-bar

-```````````````````````````````` - - -```````````````````````````````` example -foo\ - bar -. -

foo
-bar

-```````````````````````````````` - - -Line breaks can occur inside emphasis, links, and other constructs -that allow inline content: - -```````````````````````````````` example -*foo -bar* -. -

foo
-bar

-```````````````````````````````` - - -```````````````````````````````` example -*foo\ -bar* -. -

foo
-bar

-```````````````````````````````` - - -Line breaks do not occur inside code spans - -```````````````````````````````` example -`code -span` -. -

code span

-```````````````````````````````` - - -```````````````````````````````` example -`code\ -span` -. -

code\ span

-```````````````````````````````` - - -or HTML tags: - -```````````````````````````````` example -
-. -

-```````````````````````````````` - - -```````````````````````````````` example - -. -

-```````````````````````````````` - - -Hard line breaks are for separating inline content within a block. -Neither syntax for hard line breaks works at the end of a paragraph or -other block element: - -```````````````````````````````` example -foo\ -. -

foo\

-```````````````````````````````` - - -```````````````````````````````` example -foo -. -

foo

-```````````````````````````````` - - -```````````````````````````````` example -### foo\ -. -

foo\

-```````````````````````````````` - - -```````````````````````````````` example -### foo -. -

foo

-```````````````````````````````` - - -## Soft line breaks - -A regular line break (not in a code span or HTML tag) that is not -preceded by two or more spaces or a backslash is parsed as a -[softbreak](@). (A softbreak may be rendered in HTML either as a -[line ending] or as a space. The result will be the same in -browsers. In the examples here, a [line ending] will be used.) - -```````````````````````````````` example -foo -baz -. -

foo -baz

-```````````````````````````````` - - -Spaces at the end of the line and beginning of the next line are -removed: - -```````````````````````````````` example -foo - baz -. -

foo -baz

-```````````````````````````````` - - -A conforming parser may render a soft line break in HTML either as a -line break or as a space. - -A renderer may also provide an option to render soft line breaks -as hard line breaks. - -## Textual content - -Any characters not given an interpretation by the above rules will -be parsed as plain textual content. - -```````````````````````````````` example -hello $.;'there -. -

hello $.;'there

-```````````````````````````````` - - -```````````````````````````````` example -Foo χρῆν -. -

Foo χρῆν

-```````````````````````````````` - - -Internal spaces are preserved verbatim: - -```````````````````````````````` example -Multiple spaces -. -

Multiple spaces

-```````````````````````````````` - - - - -# Appendix: A parsing strategy - -In this appendix we describe some features of the parsing strategy -used in the CommonMark reference implementations. - -## Overview - -Parsing has two phases: - -1. In the first phase, lines of input are consumed and the block -structure of the document---its division into paragraphs, block quotes, -list items, and so on---is constructed. Text is assigned to these -blocks but not parsed. Link reference definitions are parsed and a -map of links is constructed. - -2. In the second phase, the raw text contents of paragraphs and headings -are parsed into sequences of Markdown inline elements (strings, -code spans, links, emphasis, and so on), using the map of link -references constructed in phase 1. - -At each point in processing, the document is represented as a tree of -**blocks**. The root of the tree is a `document` block. The `document` -may have any number of other blocks as **children**. These children -may, in turn, have other blocks as children. The last child of a block -is normally considered **open**, meaning that subsequent lines of input -can alter its contents. (Blocks that are not open are **closed**.) -Here, for example, is a possible document tree, with the open blocks -marked by arrows: - -``` tree --> document - -> block_quote - paragraph - "Lorem ipsum dolor\nsit amet." - -> list (type=bullet tight=true bullet_char=-) - list_item - paragraph - "Qui *quodsi iracundia*" - -> list_item - -> paragraph - "aliquando id" -``` - -## Phase 1: block structure - -Each line that is processed has an effect on this tree. The line is -analyzed and, depending on its contents, the document may be altered -in one or more of the following ways: - -1. One or more open blocks may be closed. -2. One or more new blocks may be created as children of the - last open block. -3. Text may be added to the last (deepest) open block remaining - on the tree. - -Once a line has been incorporated into the tree in this way, -it can be discarded, so input can be read in a stream. - -For each line, we follow this procedure: - -1. First we iterate through the open blocks, starting with the -root document, and descending through last children down to the last -open block. Each block imposes a condition that the line must satisfy -if the block is to remain open. For example, a block quote requires a -`>` character. A paragraph requires a non-blank line. -In this phase we may match all or just some of the open -blocks. But we cannot close unmatched blocks yet, because we may have a -[lazy continuation line]. - -2. Next, after consuming the continuation markers for existing -blocks, we look for new block starts (e.g. `>` for a block quote). -If we encounter a new block start, we close any blocks unmatched -in step 1 before creating the new block as a child of the last -matched block. - -3. Finally, we look at the remainder of the line (after block -markers like `>`, list markers, and indentation have been consumed). -This is text that can be incorporated into the last open -block (a paragraph, code block, heading, or raw HTML). - -Setext headings are formed when we see a line of a paragraph -that is a [setext heading underline]. - -Reference link definitions are detected when a paragraph is closed; -the accumulated text lines are parsed to see if they begin with -one or more reference link definitions. Any remainder becomes a -normal paragraph. - -We can see how this works by considering how the tree above is -generated by four lines of Markdown: - -``` markdown -> Lorem ipsum dolor -sit amet. -> - Qui *quodsi iracundia* -> - aliquando id -``` - -At the outset, our document model is just - -``` tree --> document -``` - -The first line of our text, - -``` markdown -> Lorem ipsum dolor -``` - -causes a `block_quote` block to be created as a child of our -open `document` block, and a `paragraph` block as a child of -the `block_quote`. Then the text is added to the last open -block, the `paragraph`: - -``` tree --> document - -> block_quote - -> paragraph - "Lorem ipsum dolor" -``` - -The next line, - -``` markdown -sit amet. -``` - -is a "lazy continuation" of the open `paragraph`, so it gets added -to the paragraph's text: - -``` tree --> document - -> block_quote - -> paragraph - "Lorem ipsum dolor\nsit amet." -``` - -The third line, - -``` markdown -> - Qui *quodsi iracundia* -``` - -causes the `paragraph` block to be closed, and a new `list` block -opened as a child of the `block_quote`. A `list_item` is also -added as a child of the `list`, and a `paragraph` as a child of -the `list_item`. The text is then added to the new `paragraph`: - -``` tree --> document - -> block_quote - paragraph - "Lorem ipsum dolor\nsit amet." - -> list (type=bullet tight=true bullet_char=-) - -> list_item - -> paragraph - "Qui *quodsi iracundia*" -``` - -The fourth line, - -``` markdown -> - aliquando id -``` - -causes the `list_item` (and its child the `paragraph`) to be closed, -and a new `list_item` opened up as child of the `list`. A `paragraph` -is added as a child of the new `list_item`, to contain the text. -We thus obtain the final tree: - -``` tree --> document - -> block_quote - paragraph - "Lorem ipsum dolor\nsit amet." - -> list (type=bullet tight=true bullet_char=-) - list_item - paragraph - "Qui *quodsi iracundia*" - -> list_item - -> paragraph - "aliquando id" -``` - -## Phase 2: inline structure - -Once all of the input has been parsed, all open blocks are closed. - -We then "walk the tree," visiting every node, and parse raw -string contents of paragraphs and headings as inlines. At this -point we have seen all the link reference definitions, so we can -resolve reference links as we go. - -``` tree -document - block_quote - paragraph - str "Lorem ipsum dolor" - softbreak - str "sit amet." - list (type=bullet tight=true bullet_char=-) - list_item - paragraph - str "Qui " - emph - str "quodsi iracundia" - list_item - paragraph - str "aliquando id" -``` - -Notice how the [line ending] in the first paragraph has -been parsed as a `softbreak`, and the asterisks in the first list item -have become an `emph`. - -### An algorithm for parsing nested emphasis and links - -By far the trickiest part of inline parsing is handling emphasis, -strong emphasis, links, and images. This is done using the following -algorithm. - -When we're parsing inlines and we hit either - -- a run of `*` or `_` characters, or -- a `[` or `![` - -we insert a text node with these symbols as its literal content, and we -add a pointer to this text node to the [delimiter stack](@). - -The [delimiter stack] is a doubly linked list. Each -element contains a pointer to a text node, plus information about - -- the type of delimiter (`[`, `![`, `*`, `_`) -- the number of delimiters, -- whether the delimiter is "active" (all are active to start), and -- whether the delimiter is a potential opener, a potential closer, - or both (which depends on what sort of characters precede - and follow the delimiters). - -When we hit a `]` character, we call the *look for link or image* -procedure (see below). - -When we hit the end of the input, we call the *process emphasis* -procedure (see below), with `stack_bottom` = NULL. - -#### *look for link or image* - -Starting at the top of the delimiter stack, we look backwards -through the stack for an opening `[` or `![` delimiter. - -- If we don't find one, we return a literal text node `]`. - -- If we do find one, but it's not *active*, we remove the inactive - delimiter from the stack, and return a literal text node `]`. - -- If we find one and it's active, then we parse ahead to see if - we have an inline link/image, reference link/image, compact reference - link/image, or shortcut reference link/image. - - + If we don't, then we remove the opening delimiter from the - delimiter stack and return a literal text node `]`. - - + If we do, then - - * We return a link or image node whose children are the inlines - after the text node pointed to by the opening delimiter. - - * We run *process emphasis* on these inlines, with the `[` opener - as `stack_bottom`. - - * We remove the opening delimiter. - - * If we have a link (and not an image), we also set all - `[` delimiters before the opening delimiter to *inactive*. (This - will prevent us from getting links within links.) - -#### *process emphasis* - -Parameter `stack_bottom` sets a lower bound to how far we -descend in the [delimiter stack]. If it is NULL, we can -go all the way to the bottom. Otherwise, we stop before -visiting `stack_bottom`. - -Let `current_position` point to the element on the [delimiter stack] -just above `stack_bottom` (or the first element if `stack_bottom` -is NULL). - -We keep track of the `openers_bottom` for each delimiter -type (`*`, `_`). Initialize this to `stack_bottom`. - -Then we repeat the following until we run out of potential -closers: - -- Move `current_position` forward in the delimiter stack (if needed) - until we find the first potential closer with delimiter `*` or `_`. - (This will be the potential closer closest - to the beginning of the input -- the first one in parse order.) - -- Now, look back in the stack (staying above `stack_bottom` and - the `openers_bottom` for this delimiter type) for the - first matching potential opener ("matching" means same delimiter). - -- If one is found: - - + Figure out whether we have emphasis or strong emphasis: - if both closer and opener spans have length >= 2, we have - strong, otherwise regular. - - + Insert an emph or strong emph node accordingly, after - the text node corresponding to the opener. - - + Remove any delimiters between the opener and closer from - the delimiter stack. - - + Remove 1 (for regular emph) or 2 (for strong emph) delimiters - from the opening and closing text nodes. If they become empty - as a result, remove them and remove the corresponding element - of the delimiter stack. If the closing node is removed, reset - `current_position` to the next element in the stack. - -- If none in found: - - + Set `openers_bottom` to the element before `current_position`. - (We know that there are no openers for this kind of closer up to and - including this point, so this puts a lower bound on future searches.) - - + If the closer at `current_position` is not a potential opener, - remove it from the delimiter stack (since we know it can't - be a closer either). - - + Advance `current_position` to the next element in the stack. - -After we're done, we remove all delimiters above `stack_bottom` from the -delimiter stack. - diff --git a/vendor/pulldown-cmark-0.1.2/tools/mk_entities.py b/vendor/pulldown-cmark-0.1.2/tools/mk_entities.py deleted file mode 100644 index 62d656c887..0000000000 --- a/vendor/pulldown-cmark-0.1.2/tools/mk_entities.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2015 Google Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -# get https://html.spec.whatwg.org/multipage/entities.json -# Usage: python tools/mk_entities.py entities.json > src/entities.rs - -import json -import sys - -def main(args): - jsondata = json.loads(file(args[1]).read()) - entities = [entity[1:-1] for entity in jsondata.keys() if entity.endswith(';')] - entities.sort() - print """// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Expansions of HTML5 entities - -// Autogenerated by mk_entities.py - -const ENTITIES: [&'static str; %i] = [""" % len(entities) - for e in entities: - print " \"" + e + "\"," - print """ ]; - -const ENTITY_VALUES: [&'static str; %i] = [""" % len(entities) - for e in entities: - codepoints = jsondata['&' + e + ';']["codepoints"]; - s = ''.join(['\u{%04X}' % cp for cp in codepoints]) - print " \"" + s + "\"," - print """ ]; - -pub fn get_entity(name: &str) -> Option<&'static str> { - ENTITIES.binary_search(&name).ok().map(|i| ENTITY_VALUES[i]) -} -""" - -main(sys.argv) \ No newline at end of file diff --git a/vendor/pulldown-cmark-0.1.2/tools/mk_puncttable.py b/vendor/pulldown-cmark-0.1.2/tools/mk_puncttable.py deleted file mode 100644 index 16e53b124e..0000000000 --- a/vendor/pulldown-cmark-0.1.2/tools/mk_puncttable.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2015 Google Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -# get ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt -# Usage: python tools/mk_puncttable.py UnicodeData.txt > src/puncttable.rs - -import sys - -def get_bits(high, punct): - b = 0 - for i in range(16): - if high * 16 + i in punct: - b |= 1 << i - return b - -def main(args): - ascii_punct = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" - ascii_set = set((ord(c) for c in ascii_punct)) - - punct = set() - for line in file(args[1]): - spl = line.split(';') - if spl[2] in ('Pc', 'Pd', 'Pe', 'Pf', 'Pi', 'Po', 'Ps'): - punct.add(int(spl[0], 16)) - pshift = list(set((cp // 16 for cp in punct if cp >= 128))) - pshift.sort() - bits = [get_bits(high, punct) for high in pshift] - print """// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! CommonMark punctuation set based on spec and Unicode properties. - -// Autogenerated by mk_puncttable.py - -const PUNCT_MASKS_ASCII: [u16; 8] = [""" - for x in range(8): - y = get_bits(x, ascii_set) - print ' 0x%04x, // U+%04X...U+%04X' % (y, x * 16, x * 16 + 15) - print """ ]; - -const PUNCT_TAB: [u16; %i] = [""" % len(pshift) - for x in pshift: - print ' %d, // U+%04X...U+%04X' % (x, x * 16, x * 16 + 15) - print """ ]; - -const PUNCT_MASKS: [u16; %i] = [""" % len(pshift) - for i, y in enumerate(bits): - x = pshift[i] - print ' 0x%04x, // U+%04X...U+%04X' % (y, x * 16, x * 16 + 15) - print """ ]; - -pub fn is_ascii_punctuation(c: u8) -> bool { - c < 128 && (PUNCT_MASKS_ASCII[(c / 16) as usize] & (1 << (c & 15))) != 0 -} - -pub fn is_punctuation(c: char) -> bool { - let cp = c as u32; - if cp < 128 {return is_ascii_punctuation(cp as u8); } - if cp > 0x%04X { return false; } - let high = (cp / 16) as u16; - match PUNCT_TAB.binary_search(&high) { - Ok(index) => (PUNCT_MASKS[index] & (1 << (cp & 15))) != 0, - _ => false - } -} - -#[cfg(test)] -mod tests { - use super::{is_ascii_punctuation, is_punctuation}; - - #[test] - fn test_ascii() { - assert!(is_ascii_punctuation(b'!')); - assert!(is_ascii_punctuation(b'@')); - assert!(is_ascii_punctuation(b'~')); - assert!(!is_ascii_punctuation(b' ')); - assert!(!is_ascii_punctuation(b'0')); - assert!(!is_ascii_punctuation(b'A')); - assert!(!is_ascii_punctuation(0xA1)); - } - - #[test] - fn test_unicode() { - assert!(is_punctuation('~')); - assert!(!is_punctuation(' ')); - - assert!(is_punctuation('\u{00A1}')); - assert!(is_punctuation('\u{060C}')); - assert!(is_punctuation('\u{FF65}')); - assert!(is_punctuation('\u{1BC9F}')); - assert!(!is_punctuation('\u{1BCA0}')); - } -} -""" % max(punct) - -main(sys.argv) diff --git a/vendor/punycode/.cargo-checksum.json b/vendor/punycode/.cargo-checksum.json new file mode 100644 index 0000000000..401d411913 --- /dev/null +++ b/vendor/punycode/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"00110ebf4409d26062f2ca2e5c9c8698e5f3ac14055844cf59fb989d5666b0b0","LICENSE.md":"ec2acc636afa3424bf19f691f1a419a8089a63800eecdcbf01fa08ce00f9816d","src/bin/test_decode.rs":"baf81f93360b65e7811c3c7ebacd12e44846cabde92eba06d01ab4c912fdf878","src/bin/test_encode.rs":"42fa05e383d85ef7389779c6c6c0cd9884313b60e3c16aaf5de4b92a2dad144e","src/lib.rs":"739027ba24d7c00776dfe3860195c282989586fbe939bb1dde1f313f04d45ff4"},"package":"6ddd112cca70a4d30883b2d21568a1d376ff8be4758649f64f973c6845128ad3"} \ No newline at end of file diff --git a/vendor/punycode/Cargo.toml b/vendor/punycode/Cargo.toml new file mode 100644 index 0000000000..d3afbf3341 --- /dev/null +++ b/vendor/punycode/Cargo.toml @@ -0,0 +1,15 @@ +[package] +authors = ["mcarton "] +description = "Functions to decode and encode Punycode" +keywords = ["punycode", "rfc-3492", "rfc3492"] +license = "MIT" +name = "punycode" +repository = "https://github.com/mcarton/rust-punycode.git" +version = "0.4.0" + +[dependencies] +clippy = {version = "0.0", optional = true} + +[features] +default = [] +dev = ["clippy"] diff --git a/vendor/punycode/LICENSE.md b/vendor/punycode/LICENSE.md new file mode 100644 index 0000000000..6f9d71fc6e --- /dev/null +++ b/vendor/punycode/LICENSE.md @@ -0,0 +1,24 @@ +The MIT License (MIT) + +Copyright (c) 2015 Martin Carton + + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/punycode/src/bin/test_decode.rs b/vendor/punycode/src/bin/test_decode.rs new file mode 100644 index 0000000000..4d702beb7f --- /dev/null +++ b/vendor/punycode/src/bin/test_decode.rs @@ -0,0 +1,14 @@ +extern crate punycode; + +use std::io; +use std::io::Write; + +fn main() { + let mut input = String::new(); + io::stdin().read_line(&mut input).unwrap(); + + match punycode::decode(&input) { + Ok(s) => { println!("{}", s); } + Err(..) => { writeln!(&mut std::io::stderr(), "Error").unwrap(); } + } +} diff --git a/vendor/punycode/src/bin/test_encode.rs b/vendor/punycode/src/bin/test_encode.rs new file mode 100644 index 0000000000..16286fa473 --- /dev/null +++ b/vendor/punycode/src/bin/test_encode.rs @@ -0,0 +1,11 @@ +extern crate punycode; + +use std::io; + +fn main() { + let mut input = String::new(); + io::stdin().read_line(&mut input).unwrap(); + + let s = punycode::encode(&input[0..input.len()-1]); + println!("{}", s.unwrap()); +} diff --git a/vendor/punycode/src/lib.rs b/vendor/punycode/src/lib.rs new file mode 100644 index 0000000000..c2f105d44f --- /dev/null +++ b/vendor/punycode/src/lib.rs @@ -0,0 +1,376 @@ +#![deny( + missing_copy_implementations, + missing_debug_implementations, + missing_docs, + trivial_casts, + trivial_numeric_casts, + unsafe_code, + unused_import_braces, + unused_qualifications, +)] + +#![cfg_attr(feature = "dev", feature(plugin))] +#![cfg_attr(feature = "dev", plugin(clippy))] +#![cfg_attr(feature = "dev", deny(clippy))] + +//! Fonctions to decode and encode [RFC-3492 Punycode](https://tools.ietf.org/html/rfc3492). + +use std::ascii::AsciiExt; + +// See [RFC-3492, section 4](https://tools.ietf.org/html/rfc3492#section-4). +const BASE : u32 = 36; +const TMIN : u32 = 1; +const TMAX : u32 = 26; +const SKEW : u32 = 38; +const DAMP : u32 = 700; +const INITIAL_BIAS : u32 = 72; +const INITIAL_N : u32 = 128; +const DELIMITER : char = '-'; + +/// Decode the string as Punycode. The string should not contain the initial `xn--` and must +/// contain only ASCII characters. +/// # Example +/// ``` +/// assert_eq!( +/// punycode::decode("acadmie-franaise-npb1a").unwrap(), +/// "académie-française" +/// ); +/// ``` +pub fn decode(input: &str) -> Result { + if !input.is_ascii() { + return Err(()); + } + + let mut n = INITIAL_N; + let mut i = 0; + let mut bias = INITIAL_BIAS; + + let (mut output, input) = if let Some(i) = input.rfind(DELIMITER) { + (input[0..i].chars().collect(), &input[i+1..]) + } + else { + (vec![], &input[..]) + }; + + let mut it = input.chars().peekable(); + while it.peek() != None { + let oldi = i; + let mut w = 1; + + for k in 1.. { + let c = if let Some(c) = it.next() { + c + } + else { + return Err(()); + }; + + let k = k*BASE; + + let digit = decode_digit(c); + + if digit == BASE { + return Err(()); + } + + // overflow check + if digit > (std::u32::MAX - i) / w { + return Err(()); + } + i += digit * w; + + let t = clamped_sub(TMIN, k, bias, TMAX); + if digit < t { + break; + } + + // overflow check + if BASE > (std::u32::MAX - t) / w { + return Err(()); + } + w *= BASE - t; + } + + let len = (output.len() + 1) as u32; + bias = adapt(i - oldi, len, oldi == 0); + + let il = i / len; + // overflow check + if n > std::u32::MAX - il { + return Err(()); + } + n += il; + i %= len; + + if let Some(c) = std::char::from_u32(n) { + output.insert(i as usize, c); + } + else { + return Err(()); + } + + i += 1; + } + + Ok(output.iter().cloned().collect()) +} + +/// Encode a string as punycode. The result string will contain only ASCII characters. The result +/// string does not start with `xn--`. +/// # Example +/// ``` +/// assert_eq!( +/// punycode::encode("académie-française").unwrap(), +/// "acadmie-franaise-npb1a" +/// ); +/// ``` +pub fn encode(input: &str) -> Result { + encode_slice(&input.chars().collect::>()) +} + +fn encode_slice(input: &[char]) -> Result { + let mut n = INITIAL_N; + let mut delta = 0; + let mut bias = INITIAL_BIAS; + + let mut output : String = input.iter().filter(|&&c| c.is_ascii()).cloned().collect(); + let mut h = output.len() as u32; + let b = h; + + if b > 0 { + output.push(DELIMITER) + } + + while h < input.len() as u32 { + let m = *input.iter().filter(|&&c| (c as u32) >= n).min().unwrap() as u32; + + if m - n > (std::u32::MAX - delta) / (h + 1) { + return Err(()); + } + delta += (m - n) * (h + 1); + + n = m; + + for c in input { + let c = *c as u32; + if c < n { + delta += 1; + } + else if c == n { + let mut q = delta; + + for k in 1.. { + let k = k*BASE; + + let t = clamped_sub(TMIN, k, bias, TMAX); + + if q < t { + break; + } + + output.push(encode_digit(t + (q - t) % (BASE - t))); + + q = (q - t) / (BASE - t); + } + + output.push(encode_digit(q)); + + bias = adapt(delta, h+1, h == b); + delta = 0; + h += 1; + } + } + + delta += 1; + n += 1; + } + + Ok(output) +} + +fn adapt(delta: u32, numpoint: u32, firsttime: bool) -> u32 { + let mut delta = if firsttime { + delta / DAMP + } + else { + delta / 2 + }; + + delta += delta / numpoint; + let mut k = 0; + + while delta > (BASE - TMIN) * TMAX / 2 { + delta /= BASE - TMIN; + k += BASE + } + + k + (BASE - TMIN + 1) * delta / (delta + SKEW) +} + +/// Compute `lhs-rhs`. Result will be clamped in [min, max]. +fn clamped_sub(min: T, lhs: T, rhs: T, max: T) -> T +where T : Ord + + std::ops::Add + + std::ops::Sub + + Copy +{ + if min + rhs >= lhs { min } + else if max + rhs <= lhs { max } + else { lhs - rhs } +} + +fn decode_digit(c: char) -> u32 { + let cp = c as u32; + + match c { + '0' ... '9' => cp - ('0' as u32) + 26, + 'A' ... 'Z' => cp - ('A' as u32), + 'a' ... 'z' => cp - ('a' as u32), + _ => BASE, + } +} + +fn encode_digit(d: u32) -> char { + let r = (d + 22 + (if d < 26 { 75 } else { 0 })) as u8 as char; + + assert!(('0' <= r && r <= '9') || ('a' <= r && r <= 'z'), "r = {}", r); + + r +} + +#[cfg(test)] +static TESTS: &'static [(&'static str, &'static str)] = &[ + // examples taken from [RCF-3492, section 7.1](https://tools.ietf.org/html/rfc3492#section-7.1) + (&"\u{0644}\u{064A}\u{0647}\u{0645}\u{0627}\u{0628}\u{062A}\u{0643}\u{0644}\ + \u{0645}\u{0648}\u{0634}\u{0639}\u{0631}\u{0628}\u{064A}\u{061F}", + &"egbpdaj6bu4bxfgehfvwxn"), + + (&"\u{4ED6}\u{4EEC}\u{4E3A}\u{4EC0}\u{4E48}\u{4E0D}\u{8BF4}\u{4E2D}\u{6587}", + &"ihqwcrb4cv8a8dqg056pqjye"), + + (&"\u{4ED6}\u{5011}\u{7232}\u{4EC0}\u{9EBD}\u{4E0D}\u{8AAA}\u{4E2D}\u{6587}", + &"ihqwctvzc91f659drss3x8bo0yb"), + + (&"\u{0050}\u{0072}\u{006F}\u{010D}\u{0070}\u{0072}\u{006F}\u{0073}\u{0074}\ + \u{011B}\u{006E}\u{0065}\u{006D}\u{006C}\u{0075}\u{0076}\u{00ED}\u{010D}\ + \u{0065}\u{0073}\u{006B}\u{0079}", + &"Proprostnemluvesky-uyb24dma41a"), + + (&"\u{05DC}\u{05DE}\u{05D4}\u{05D4}\u{05DD}\u{05E4}\u{05E9}\u{05D5}\u{05D8}\ + \u{05DC}\u{05D0}\u{05DE}\u{05D3}\u{05D1}\u{05E8}\u{05D9}\u{05DD}\u{05E2}\ + \u{05D1}\u{05E8}\u{05D9}\u{05EA}", + &"4dbcagdahymbxekheh6e0a7fei0b"), + + (&"\u{092F}\u{0939}\u{0932}\u{094B}\u{0917}\u{0939}\u{093F}\u{0928}\u{094D}\ + \u{0926}\u{0940}\u{0915}\u{094D}\u{092F}\u{094B}\u{0902}\u{0928}\u{0939}\ + \u{0940}\u{0902}\u{092C}\u{094B}\u{0932}\u{0938}\u{0915}\u{0924}\u{0947}\ + \u{0939}\u{0948}\u{0902}", + &"i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd"), + + (&"\u{306A}\u{305C}\u{307F}\u{3093}\u{306A}\u{65E5}\u{672C}\u{8A9E}\u{3092}\ + \u{8A71}\u{3057}\u{3066}\u{304F}\u{308C}\u{306A}\u{3044}\u{306E}\u{304B}", + &"n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa"), + + (&"\u{C138}\u{ACC4}\u{C758}\u{BAA8}\u{B4E0}\u{C0AC}\u{B78C}\u{B4E4}\u{C774}\ + \u{D55C}\u{AD6D}\u{C5B4}\u{B97C}\u{C774}\u{D574}\u{D55C}\u{B2E4}\u{BA74}\ + \u{C5BC}\u{B9C8}\u{B098}\u{C88B}\u{C744}\u{AE4C}", + &"989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c"), + + (&"\u{043F}\u{043E}\u{0447}\u{0435}\u{043C}\u{0443}\u{0436}\u{0435}\u{043E}\ + \u{043D}\u{0438}\u{043D}\u{0435}\u{0433}\u{043E}\u{0432}\u{043E}\u{0440}\ + \u{044F}\u{0442}\u{043F}\u{043E}\u{0440}\u{0443}\u{0441}\u{0441}\u{043A}\ + \u{0438}", + &"b1abfaaepdrnnbgefbaDotcwatmq2g4l"), + + (&"\u{0050}\u{006F}\u{0072}\u{0071}\u{0075}\u{00E9}\u{006E}\u{006F}\u{0070}\ + \u{0075}\u{0065}\u{0064}\u{0065}\u{006E}\u{0073}\u{0069}\u{006D}\u{0070}\ + \u{006C}\u{0065}\u{006D}\u{0065}\u{006E}\u{0074}\u{0065}\u{0068}\u{0061}\ + \u{0062}\u{006C}\u{0061}\u{0072}\u{0065}\u{006E}\u{0045}\u{0073}\u{0070}\ + \u{0061}\u{00F1}\u{006F}\u{006C}", + &"PorqunopuedensimplementehablarenEspaol-fmd56a"), + + (&"\u{0054}\u{1EA1}\u{0069}\u{0073}\u{0061}\u{006F}\u{0068}\u{1ECD}\u{006B}\ + \u{0068}\u{00F4}\u{006E}\u{0067}\u{0074}\u{0068}\u{1EC3}\u{0063}\u{0068}\ + \u{1EC9}\u{006E}\u{00F3}\u{0069}\u{0074}\u{0069}\u{1EBF}\u{006E}\u{0067}\ + \u{0056}\u{0069}\u{1EC7}\u{0074}", + &"TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g"), + + (&"\u{0033}\u{5E74}\u{0042}\u{7D44}\u{91D1}\u{516B}\u{5148}\u{751F}", + &"3B-ww4c5e180e575a65lsy2b"), + + (&"\u{5B89}\u{5BA4}\u{5948}\u{7F8E}\u{6075}\u{002D}\u{0077}\u{0069}\u{0074}\ + \u{0068}\u{002D}\u{0053}\u{0055}\u{0050}\u{0045}\u{0052}\u{002D}\u{004D}\ + \u{004F}\u{004E}\u{004B}\u{0045}\u{0059}\u{0053}", + &"-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n"), + + (&"\u{0048}\u{0065}\u{006C}\u{006C}\u{006F}\u{002D}\u{0041}\u{006E}\u{006F}\ + \u{0074}\u{0068}\u{0065}\u{0072}\u{002D}\u{0057}\u{0061}\u{0079}\u{002D}\ + \u{305D}\u{308C}\u{305E}\u{308C}\u{306E}\u{5834}\u{6240}", + &"Hello-Another-Way--fc4qua05auwb3674vfr0b"), + + (&"\u{3072}\u{3068}\u{3064}\u{5C4B}\u{6839}\u{306E}\u{4E0B}\u{0032}", + &"2-u9tlzr9756bt3uc0v"), + + (&"\u{004D}\u{0061}\u{006A}\u{0069}\u{3067}\u{004B}\u{006F}\u{0069}\u{3059}\ + \u{308B}\u{0035}\u{79D2}\u{524D}", + &"MajiKoi5-783gue6qz075azm5e"), + + (&"\u{30D1}\u{30D5}\u{30A3}\u{30FC}\u{0064}\u{0065}\u{30EB}\u{30F3}\u{30D0}", + &"de-jg4avhby1noc0d"), + + (&"\u{305D}\u{306E}\u{30B9}\u{30D4}\u{30FC}\u{30C9}\u{3067}", + &"d9juau41awczczp"), + + (&"\u{002D}\u{003E}\u{0020}\u{0024}\u{0031}\u{002E}\u{0030}\u{0030}\u{0020}\ + \u{003C}\u{002D}", + &"-> $1.00 <--"), + + // some real-life examples + (&"académie-française", &"acadmie-franaise-npb1a"), + (&"bücher", &"bcher-kva"), + (&"république-numérique", &"rpublique-numrique-bwbm"), + + // some real-life TLD + (&"бг", &"90ae"), + (&"рф", &"p1ai"), + (&"укр", &"j1amh"), + (&"السعودية", &"mgberp4a5d4ar"), + (&"امارات", &"mgbaam7a8h"), + (&"مصر", &"wgbh1c"), + (&"中国", &"fiqs8s"), + (&"中國", &"fiqz9s"), + (&"台湾", &"kprw13d"), + (&"台灣", &"kpry57d"), + (&"香港", &"j6w193g"), + + // other + (&"", &""), + (&"a", &"a-"), + (&"0", &"0-"), + (&"A", &"A-"), + (&"é", &"9ca"), + (&"\n", &"\n-"), +]; + +#[test] +fn test_decode() { + for t in TESTS { + assert_eq!(decode(&t.1), Ok(t.0.into())); + } +} + +#[test] +fn test_encode() { + for t in TESTS { + assert_eq!(encode(t.0).unwrap().to_lowercase(), t.1.to_lowercase()); + } +} + +#[test] +fn test_fail_decode() { + assert_eq!(decode(&"bcher-kva.ch"), Err(())); + assert_eq!(decode(&"+"), Err(())); + assert_eq!(decode(&"\\"), Err(())); + assert_eq!(decode(&"é"), Err(())); + assert_eq!(decode(&"99999999"), Err(())); +} diff --git a/vendor/quote/.cargo-checksum.json b/vendor/quote/.cargo-checksum.json index f1a67ee811..0b16c810ab 100644 --- a/vendor/quote/.cargo-checksum.json +++ b/vendor/quote/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"44cf9d3a28be1b21f4247572b6ca4d38dc3fd42fa84c4a4e0e5632aa27bee083","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"b43ef9b9c61628f8de7036271e61322cba23d878d056748e571f4f6cf9fba1b1","src/ext.rs":"a2def0b0f24c822b3f936a781c347e5f6fdc75120f85874c94f5e7eb708168c2","src/lib.rs":"f1ba768690c57252e8135ee474a20bdd513fd0bd0664e9e9b697800163f39d08","src/to_tokens.rs":"86c419a72017846ef33a0acc53caee7312c750c90b3f1d3b58e33f20efcb94f4","tests/conditional/integer128.rs":"d83e21a91efbaa801a82ae499111bdda2d31edaa620e78c0199eba42d69c9ee6","tests/test.rs":"810013d7fd77b738abd0ace90ce2f2f3e219c757652eabab29bc1c0ce4a73b24"},"package":"53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"} \ No newline at end of file +{"files":{"Cargo.toml":"cc812f89636414ac5e7d47651d50586d6e919b1ac0e6f3d9eba7125967da9287","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"d9392d4c7af3bf9714f0a95801d64de46ffd4558cdfeea0eb85b414e555abb72","src/ext.rs":"03919239a20f8393288783a21bf6fdee12e405d13d162c9faa6f8f5ce54b003b","src/lib.rs":"c245eda59e7c953b809e00fa06ab3b61db0d5a248a85b7e4b6d5f979c977be68","src/runtime.rs":"f579bd977eae678b119eb6904d126870fe69b51e09d400abb3ec10294140926b","src/to_tokens.rs":"5b4155ff36262fb81f98ca8a9e903e9cf1ca346e72cb36a2de746e10d3b24d49","tests/conditional/integer128.rs":"d83e21a91efbaa801a82ae499111bdda2d31edaa620e78c0199eba42d69c9ee6","tests/test.rs":"810013d7fd77b738abd0ace90ce2f2f3e219c757652eabab29bc1c0ce4a73b24"},"package":"faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"} \ No newline at end of file diff --git a/vendor/quote/Cargo.toml b/vendor/quote/Cargo.toml index c2c73ac9ea..02a98955da 100644 --- a/vendor/quote/Cargo.toml +++ b/vendor/quote/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "quote" -version = "0.6.10" +version = "0.6.12" authors = ["David Tolnay "] include = ["Cargo.toml", "src/**/*.rs", "tests/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] description = "Quasi-quoting macro quote!(...)" diff --git a/vendor/quote/README.md b/vendor/quote/README.md index 00232cd38b..759916ace2 100644 --- a/vendor/quote/README.md +++ b/vendor/quote/README.md @@ -38,18 +38,11 @@ first support for procedural macros in Rust 1.15.0.* quote = "0.6" ``` -```rust -#[macro_use] -extern crate quote; -``` - ## Syntax The quote crate provides a [`quote!`] macro within which you can write Rust code that gets packaged into a [`TokenStream`] and can be treated as data. You should -think of `TokenStream` as representing a fragment of Rust source code. This type -can be returned directly back to the compiler by a procedural macro to get -compiled into the caller's crate. +think of `TokenStream` as representing a fragment of Rust source code. [`TokenStream`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.TokenStream.html @@ -64,7 +57,7 @@ most Rust primitive types as well as most of the syntax tree types from [`syn`]. let tokens = quote! { struct SerializeWith #generics #where_clause { value: &'a #field_ty, - phantom: ::std::marker::PhantomData<#item_ty>, + phantom: core::marker::PhantomData<#item_ty>, } impl #generics serde::Serialize for SerializeWith #generics #where_clause { @@ -78,7 +71,7 @@ let tokens = quote! { SerializeWith { value: #value, - phantom: ::std::marker::PhantomData::<#item_ty>, + phantom: core::marker::PhantomData::<#item_ty>, } }; ``` @@ -100,6 +93,107 @@ Note that there is a difference between `#(#var ,)*` and `#(#var),*`—the latte does not produce a trailing comma. This matches the behavior of delimiters in `macro_rules!`. +## Returning tokens to the compiler + +The `quote!` macro evaluates to an expression of type +`proc_macro2::TokenStream`. Meanwhile Rust procedural macros are expected to +return the type `proc_macro::TokenStream`. + +The difference between the two types is that `proc_macro` types are entirely +specific to procedural macros and cannot ever exist in code outside of a +procedural macro, while `proc_macro2` types may exist anywhere including tests +and non-macro code like main.rs and build.rs. This is why even the procedural +macro ecosystem is largely built around `proc_macro2`, because that ensures the +libraries are unit testable and accessible in non-macro contexts. + +There is a [`From`]-conversion in both directions so returning the output of +`quote!` from a procedural macro usually looks like `tokens.into()` or +`proc_macro::TokenStream::from(tokens)`. + +[`From`]: https://doc.rust-lang.org/std/convert/trait.From.html + +## Examples + +### Combining quoted fragments + +Usually you don't end up constructing an entire final `TokenStream` in one +piece. Different parts may come from different helper functions. The tokens +produced by `quote!` themselves implement `ToTokens` and so can be interpolated +into later `quote!` invocations to build up a final result. + +```rust +let type_definition = quote! {...}; +let methods = quote! {...}; + +let tokens = quote! { + #type_definition + #methods +}; +``` + +### Constructing identifiers + +Suppose we have an identifier `ident` which came from somewhere in a macro +input and we need to modify it in some way for the macro output. Let's consider +prepending the identifier with an underscore. + +Simply interpolating the identifier next to an underscore will not have the +behavior of concatenating them. The underscore and the identifier will continue +to be two separate tokens as if you had written `_ x`. + +```rust +// incorrect +quote! { + let mut _#ident = 0; +} +``` + +The solution is to perform token-level manipulations using the APIs provided by +Syn and proc-macro2. + +```rust +let concatenated = format!("_{}", ident); +let varname = syn::Ident::new(&concatenated, ident.span()); +quote! { + let mut #varname = 0; +} +``` + +### Making method calls + +Let's say our macro requires some type specified in the macro input to have a +constructor called `new`. We have the type in a variable called `field_type` of +type `syn::Type` and want to invoke the constructor. + +```rust +// incorrect +quote! { + let value = #field_type::new(); +} +``` + +This works only sometimes. If `field_type` is `String`, the expanded code +contains `String::new()` which is fine. But if `field_type` is something like +`Vec` then the expanded code is `Vec::new()` which is invalid syntax. +Ordinarily in handwritten Rust we would write `Vec::::new()` but for macros +often the following is more convenient. + +```rust +quote! { + let value = <#field_type>::new(); +} +``` + +This expands to `>::new()` which behaves correctly. + +A similar pattern is appropriate for trait methods. + +```rust +quote! { + let value = <#field_type as core::default::Default>::default(); +} +``` + ## Hygiene Any interpolated tokens preserve the `Span` information provided by their diff --git a/vendor/quote/src/ext.rs b/vendor/quote/src/ext.rs index 614e1e1b2d..7ebbe30a1b 100644 --- a/vendor/quote/src/ext.rs +++ b/vendor/quote/src/ext.rs @@ -8,21 +8,49 @@ use proc_macro2::{TokenStream, TokenTree}; /// /// This trait is sealed and cannot be implemented outside of the `quote` crate. pub trait TokenStreamExt: private::Sealed { + /// For use by `ToTokens` implementations. + /// + /// Appends the token specified to this list of tokens. fn append(&mut self, token: U) where U: Into; + /// For use by `ToTokens` implementations. + /// + /// ```edition2018 + /// # use quote::{quote, TokenStreamExt, ToTokens}; + /// # use proc_macro2::TokenStream; + /// # + /// struct X; + /// + /// impl ToTokens for X { + /// fn to_tokens(&self, tokens: &mut TokenStream) { + /// tokens.append_all(&[true, false]); + /// } + /// } + /// + /// let tokens = quote!(#X); + /// assert_eq!(tokens.to_string(), "true false"); + /// ``` fn append_all(&mut self, iter: I) where T: ToTokens, I: IntoIterator; + /// For use by `ToTokens` implementations. + /// + /// Appends all of the items in the iterator `I`, separated by the tokens + /// `U`. fn append_separated(&mut self, iter: I, op: U) where T: ToTokens, I: IntoIterator, U: ToTokens; + /// For use by `ToTokens` implementations. + /// + /// Appends all tokens in the iterator `I`, appending `U` after each + /// element, including after the last element of the iterator. fn append_terminated(&mut self, iter: I, term: U) where T: ToTokens, @@ -31,9 +59,6 @@ pub trait TokenStreamExt: private::Sealed { } impl TokenStreamExt for TokenStream { - /// For use by `ToTokens` implementations. - /// - /// Appends the token specified to this list of tokens. fn append(&mut self, token: U) where U: Into, @@ -41,26 +66,6 @@ impl TokenStreamExt for TokenStream { self.extend(iter::once(token.into())); } - /// For use by `ToTokens` implementations. - /// - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate proc_macro2; - /// # use quote::{TokenStreamExt, ToTokens}; - /// # use proc_macro2::TokenStream; - /// # fn main() { - /// struct X; - /// - /// impl ToTokens for X { - /// fn to_tokens(&self, tokens: &mut TokenStream) { - /// tokens.append_all(&[true, false]); - /// } - /// } - /// - /// let tokens = quote!(#X); - /// assert_eq!(tokens.to_string(), "true false"); - /// # } - /// ``` fn append_all(&mut self, iter: I) where T: ToTokens, @@ -71,10 +76,6 @@ impl TokenStreamExt for TokenStream { } } - /// For use by `ToTokens` implementations. - /// - /// Appends all of the items in the iterator `I`, separated by the tokens - /// `U`. fn append_separated(&mut self, iter: I, op: U) where T: ToTokens, @@ -89,10 +90,6 @@ impl TokenStreamExt for TokenStream { } } - /// For use by `ToTokens` implementations. - /// - /// Appends all tokens in the iterator `I`, appending `U` after each - /// element, including after the last element of the iterator. fn append_terminated(&mut self, iter: I, term: U) where T: ToTokens, diff --git a/vendor/quote/src/lib.rs b/vendor/quote/src/lib.rs index 8f0203b8e0..a71d8af4c3 100644 --- a/vendor/quote/src/lib.rs +++ b/vendor/quote/src/lib.rs @@ -29,13 +29,6 @@ //! quote = "0.6" //! ``` //! -//! ``` -//! #[macro_use] -//! extern crate quote; -//! # -//! # fn main() {} -//! ``` -//! //! # Example //! //! The following quasi-quoted block of code is something you might find in [a] @@ -48,22 +41,20 @@ //! [a]: https://serde.rs/ //! [`quote_spanned!`]: macro.quote_spanned.html //! -//! ``` -//! # #[macro_use] -//! # extern crate quote; +//! ```edition2018 +//! # use quote::quote; //! # -//! # fn main() { -//! # let generics = ""; -//! # let where_clause = ""; -//! # let field_ty = ""; -//! # let item_ty = ""; -//! # let path = ""; -//! # let value = ""; +//! # let generics = ""; +//! # let where_clause = ""; +//! # let field_ty = ""; +//! # let item_ty = ""; +//! # let path = ""; +//! # let value = ""; //! # //! let tokens = quote! { //! struct SerializeWith #generics #where_clause { //! value: &'a #field_ty, -//! phantom: ::std::marker::PhantomData<#item_ty>, +//! phantom: core::marker::PhantomData<#item_ty>, //! } //! //! impl #generics serde::Serialize for SerializeWith #generics #where_clause { @@ -77,14 +68,12 @@ //! //! SerializeWith { //! value: #value, -//! phantom: ::std::marker::PhantomData::<#item_ty>, +//! phantom: core::marker::PhantomData::<#item_ty>, //! } //! }; -//! # -//! # } //! ``` //! -//! ## Recursion limit +//! # Recursion limit //! //! The `quote!` macro relies on deep recursion so some large invocations may //! fail with "recursion limit reached" when you compile. If it fails, bump up @@ -92,7 +81,7 @@ //! An even higher limit may be necessary for especially large invocations. // Quote types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/quote/0.6.10")] +#![doc(html_root_url = "https://docs.rs/quote/0.6.12")] #[cfg(all( not(all(target_arch = "wasm32", target_os = "unknown")), @@ -109,130 +98,8 @@ pub use to_tokens::ToTokens; // Not public API. #[doc(hidden)] -pub mod __rt { - use ext::TokenStreamExt; - pub use proc_macro2::*; - - fn is_ident_start(c: u8) -> bool { - (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_' - } - - fn is_ident_continue(c: u8) -> bool { - (b'a' <= c && c <= b'z') - || (b'A' <= c && c <= b'Z') - || c == b'_' - || (b'0' <= c && c <= b'9') - } - - fn is_ident(token: &str) -> bool { - if token.bytes().all(|digit| digit >= b'0' && digit <= b'9') { - return false; - } - - let mut bytes = token.bytes(); - let first = bytes.next().unwrap(); - if !is_ident_start(first) { - return false; - } - for ch in bytes { - if !is_ident_continue(ch) { - return false; - } - } - true - } - - pub fn parse(tokens: &mut TokenStream, span: Span, s: &str) { - if is_ident(s) { - // Fast path, since idents are the most common token. - tokens.append(Ident::new(s, span)); - } else { - let s: TokenStream = s.parse().expect("invalid token stream"); - tokens.extend(s.into_iter().map(|mut t| { - t.set_span(span); - t - })); - } - } - - macro_rules! push_punct { - ($name:ident $char1:tt) => { - pub fn $name(tokens: &mut TokenStream, span: Span) { - let mut punct = Punct::new($char1, Spacing::Alone); - punct.set_span(span); - tokens.append(punct); - } - }; - ($name:ident $char1:tt $char2:tt) => { - pub fn $name(tokens: &mut TokenStream, span: Span) { - let mut punct = Punct::new($char1, Spacing::Joint); - punct.set_span(span); - tokens.append(punct); - let mut punct = Punct::new($char2, Spacing::Alone); - punct.set_span(span); - tokens.append(punct); - } - }; - ($name:ident $char1:tt $char2:tt $char3:tt) => { - pub fn $name(tokens: &mut TokenStream, span: Span) { - let mut punct = Punct::new($char1, Spacing::Joint); - punct.set_span(span); - tokens.append(punct); - let mut punct = Punct::new($char2, Spacing::Joint); - punct.set_span(span); - tokens.append(punct); - let mut punct = Punct::new($char3, Spacing::Alone); - punct.set_span(span); - tokens.append(punct); - } - }; - } - - push_punct!(push_add '+'); - push_punct!(push_add_eq '+' '='); - push_punct!(push_and '&'); - push_punct!(push_and_and '&' '&'); - push_punct!(push_and_eq '&' '='); - push_punct!(push_at '@'); - push_punct!(push_bang '!'); - push_punct!(push_caret '^'); - push_punct!(push_caret_eq '^' '='); - push_punct!(push_colon ':'); - push_punct!(push_colon2 ':' ':'); - push_punct!(push_comma ','); - push_punct!(push_div '/'); - push_punct!(push_div_eq '/' '='); - push_punct!(push_dot '.'); - push_punct!(push_dot2 '.' '.'); - push_punct!(push_dot3 '.' '.' '.'); - push_punct!(push_dot_dot_eq '.' '.' '='); - push_punct!(push_eq '='); - push_punct!(push_eq_eq '=' '='); - push_punct!(push_ge '>' '='); - push_punct!(push_gt '>'); - push_punct!(push_le '<' '='); - push_punct!(push_lt '<'); - push_punct!(push_mul_eq '*' '='); - push_punct!(push_ne '!' '='); - push_punct!(push_or '|'); - push_punct!(push_or_eq '|' '='); - push_punct!(push_or_or '|' '|'); - push_punct!(push_pound '#'); - push_punct!(push_question '?'); - push_punct!(push_rarrow '-' '>'); - push_punct!(push_larrow '<' '-'); - push_punct!(push_rem '%'); - push_punct!(push_rem_eq '%' '='); - push_punct!(push_fat_arrow '=' '>'); - push_punct!(push_semi ';'); - push_punct!(push_shl '<' '<'); - push_punct!(push_shl_eq '<' '<' '='); - push_punct!(push_shr '>' '>'); - push_punct!(push_shr_eq '>' '>' '='); - push_punct!(push_star '*'); - push_punct!(push_sub '-'); - push_punct!(push_sub_eq '-' '='); -} +#[path = "runtime.rs"] +pub mod __rt; /// The whole point. /// @@ -265,6 +132,20 @@ pub mod __rt { /// - `#( struct #var; )*` — the repetition can contain other tokens /// - `#( #k => println!("{}", #v), )*` — even multiple interpolations /// +/// There are two limitations around interpolations in a repetition: +/// +/// - Every interpolation inside of a repetition must be a distinct variable. +/// That is, `#(#a #a)*` is not allowed. Work around this by collecting `a` +/// into a vector and taking references `a1 = &a` and `a2 = &a` which you use +/// inside the repetition: `#(#a1 #a2)*`. Where possible, use meaningful names +/// that indicate the distinct role of each copy. +/// +/// - Every interpolation inside of a repetition must be iterable. If we have +/// `vec` which is a vector and `ident` which is a single identifier, +/// `#(#ident #vec)*` is not allowed. Work around this by using +/// `std::iter::repeat(ident)` to produce an iterable that can be used from +/// within the repetition. +/// /// # Hygiene /// /// Any interpolated tokens preserve the `Span` information provided by their @@ -277,17 +158,43 @@ pub mod __rt { /// /// [`quote_spanned!`]: macro.quote_spanned.html /// -/// # Example +/// # Return type /// -/// ``` +/// The macro evaluates to an expression of type `proc_macro2::TokenStream`. +/// Meanwhile Rust procedural macros are expected to return the type +/// `proc_macro::TokenStream`. +/// +/// The difference between the two types is that `proc_macro` types are entirely +/// specific to procedural macros and cannot ever exist in code outside of a +/// procedural macro, while `proc_macro2` types may exist anywhere including +/// tests and non-macro code like main.rs and build.rs. This is why even the +/// procedural macro ecosystem is largely built around `proc_macro2`, because +/// that ensures the libraries are unit testable and accessible in non-macro +/// contexts. +/// +/// There is a [`From`]-conversion in both directions so returning the output of +/// `quote!` from a procedural macro usually looks like `tokens.into()` or +/// `proc_macro::TokenStream::from(tokens)`. +/// +/// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html +/// +/// # Examples +/// +/// ## Procedural macro +/// +/// The structure of a basic procedural macro is as follows. Refer to the [Syn] +/// crate for further useful guidance on using `quote!` as part of a procedural +/// macro. +/// +/// [Syn]: https://github.com/dtolnay/syn +/// +/// ```edition2018 /// # #[cfg(any())] /// extern crate proc_macro; -/// # extern crate proc_macro2 as proc_macro; -/// -/// #[macro_use] -/// extern crate quote; +/// # use proc_macro2 as proc_macro; /// /// use proc_macro::TokenStream; +/// use quote::quote; /// /// # const IGNORE_TOKENS: &'static str = stringify! { /// #[proc_macro_derive(HeapSize)] @@ -304,7 +211,7 @@ pub mod __rt { /// /// let expanded = quote! { /// // The generated impl. -/// impl ::heapsize::HeapSize for #name { +/// impl heapsize::HeapSize for #name { /// fn heap_size_of_children(&self) -> usize { /// #expr /// } @@ -312,14 +219,123 @@ pub mod __rt { /// }; /// /// // Hand the output tokens back to the compiler. -/// expanded.into() +/// TokenStream::from(expanded) +/// } +/// ``` +/// +/// ## Combining quoted fragments +/// +/// Usually you don't end up constructing an entire final `TokenStream` in one +/// piece. Different parts may come from different helper functions. The tokens +/// produced by `quote!` themselves implement `ToTokens` and so can be +/// interpolated into later `quote!` invocations to build up a final result. +/// +/// ```edition2018 +/// # use quote::quote; +/// # +/// let type_definition = quote! {...}; +/// let methods = quote! {...}; +/// +/// let tokens = quote! { +/// #type_definition +/// #methods +/// }; +/// ``` +/// +/// ## Constructing identifiers +/// +/// Suppose we have an identifier `ident` which came from somewhere in a macro +/// input and we need to modify it in some way for the macro output. Let's +/// consider prepending the identifier with an underscore. +/// +/// Simply interpolating the identifier next to an underscore will not have the +/// behavior of concatenating them. The underscore and the identifier will +/// continue to be two separate tokens as if you had written `_ x`. +/// +/// ```edition2018 +/// # use proc_macro2::{self as syn, Span}; +/// # use quote::quote; +/// # +/// # let ident = syn::Ident::new("i", Span::call_site()); +/// # +/// // incorrect +/// quote! { +/// let mut _#ident = 0; +/// } +/// # ; +/// ``` +/// +/// The solution is to perform token-level manipulations using the APIs provided +/// by Syn and proc-macro2. +/// +/// ```edition2018 +/// # use proc_macro2::{self as syn, Span}; +/// # use quote::quote; +/// # +/// # let ident = syn::Ident::new("i", Span::call_site()); +/// # +/// let concatenated = format!("_{}", ident); +/// let varname = syn::Ident::new(&concatenated, ident.span()); +/// quote! { +/// let mut #varname = 0; +/// } +/// # ; +/// ``` +/// +/// ## Making method calls +/// +/// Let's say our macro requires some type specified in the macro input to have +/// a constructor called `new`. We have the type in a variable called +/// `field_type` of type `syn::Type` and want to invoke the constructor. +/// +/// ```edition2018 +/// # use quote::quote; +/// # +/// # let field_type = quote!(...); +/// # +/// // incorrect +/// quote! { +/// let value = #field_type::new(); +/// } +/// # ; +/// ``` +/// +/// This works only sometimes. If `field_type` is `String`, the expanded code +/// contains `String::new()` which is fine. But if `field_type` is something +/// like `Vec` then the expanded code is `Vec::new()` which is invalid +/// syntax. Ordinarily in handwritten Rust we would write `Vec::::new()` +/// but for macros often the following is more convenient. +/// +/// ```edition2018 +/// # use quote::quote; +/// # +/// # let field_type = quote!(...); +/// # +/// quote! { +/// let value = <#field_type>::new(); /// } +/// # ; +/// ``` +/// +/// This expands to `>::new()` which behaves correctly. +/// +/// A similar pattern is appropriate for trait methods. +/// +/// ```edition2018 +/// # use quote::quote; +/// # +/// # let field_type = quote!(...); /// # -/// # fn main() {} +/// quote! { +/// let value = <#field_type as core::default::Default>::default(); +/// } +/// # ; /// ``` #[macro_export(local_inner_macros)] macro_rules! quote { - ($($tt:tt)*) => (quote_spanned!($crate::__rt::Span::call_site()=> $($tt)*)); + ($($tt:tt)*) => { + quote_spanned!($crate::__rt::Span::call_site()=> $($tt)*) + }; } /// Same as `quote!`, but applies a given span to all tokens originating within @@ -333,14 +349,10 @@ macro_rules! quote { /// /// [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html /// -/// ``` -/// # #[macro_use] -/// # extern crate quote; -/// # extern crate proc_macro2; -/// # +/// ```edition2018 /// # use proc_macro2::Span; +/// # use quote::quote_spanned; /// # -/// # fn main() { /// # const IGNORE_TOKENS: &'static str = stringify! { /// let span = /* ... */; /// # }; @@ -354,7 +366,6 @@ macro_rules! quote { /// let tokens = quote_spanned! {span=> /// Box::into_raw(Box::new(#init)) /// }; -/// # } /// ``` /// /// The lack of space before the `=>` should look jarring to Rust programmers @@ -377,12 +388,8 @@ macro_rules! quote { /// /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// -/// ``` -/// # #[macro_use] -/// # extern crate quote; -/// # extern crate proc_macro2; -/// # -/// # use quote::{TokenStreamExt, ToTokens}; +/// ```edition2018 +/// # use quote::{quote_spanned, TokenStreamExt, ToTokens}; /// # use proc_macro2::{Span, TokenStream}; /// # /// # struct Type; @@ -397,7 +404,6 @@ macro_rules! quote { /// # fn to_tokens(&self, _tokens: &mut TokenStream) {} /// # } /// # -/// # fn main() { /// # let ty = Type; /// # let call_site = Span::call_site(); /// # @@ -405,7 +411,6 @@ macro_rules! quote { /// let assert_sync = quote_spanned! {ty_span=> /// struct _AssertSync where #ty: Sync; /// }; -/// # } /// ``` /// /// If the assertion fails, the user will see an error like the following. The @@ -428,14 +433,12 @@ macro_rules! quote { /// named `Sync` that is implemented for their type. #[macro_export(local_inner_macros)] macro_rules! quote_spanned { - ($span:expr=> $($tt:tt)*) => { - { - let mut _s = $crate::__rt::TokenStream::new(); - let _span = $span; - quote_each_token!(_s _span $($tt)*); - _s - } - }; + ($span:expr=> $($tt:tt)*) => {{ + let mut _s = $crate::__rt::TokenStream::new(); + let _span = $span; + quote_each_token!(_s _span $($tt)*); + _s + }}; } // Extract the names of all #metavariables and pass them to the $finish macro. diff --git a/vendor/quote/src/runtime.rs b/vendor/quote/src/runtime.rs new file mode 100644 index 0000000000..715a87707b --- /dev/null +++ b/vendor/quote/src/runtime.rs @@ -0,0 +1,119 @@ +use ext::TokenStreamExt; +pub use proc_macro2::*; + +fn is_ident_start(c: u8) -> bool { + (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_' +} + +fn is_ident_continue(c: u8) -> bool { + (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_' || (b'0' <= c && c <= b'9') +} + +fn is_ident(token: &str) -> bool { + if token.bytes().all(|digit| digit >= b'0' && digit <= b'9') { + return false; + } + + let mut bytes = token.bytes(); + let first = bytes.next().unwrap(); + if !is_ident_start(first) { + return false; + } + for ch in bytes { + if !is_ident_continue(ch) { + return false; + } + } + true +} + +pub fn parse(tokens: &mut TokenStream, span: Span, s: &str) { + if is_ident(s) { + // Fast path, since idents are the most common token. + tokens.append(Ident::new(s, span)); + } else { + let s: TokenStream = s.parse().expect("invalid token stream"); + tokens.extend(s.into_iter().map(|mut t| { + t.set_span(span); + t + })); + } +} + +macro_rules! push_punct { + ($name:ident $char1:tt) => { + pub fn $name(tokens: &mut TokenStream, span: Span) { + let mut punct = Punct::new($char1, Spacing::Alone); + punct.set_span(span); + tokens.append(punct); + } + }; + ($name:ident $char1:tt $char2:tt) => { + pub fn $name(tokens: &mut TokenStream, span: Span) { + let mut punct = Punct::new($char1, Spacing::Joint); + punct.set_span(span); + tokens.append(punct); + let mut punct = Punct::new($char2, Spacing::Alone); + punct.set_span(span); + tokens.append(punct); + } + }; + ($name:ident $char1:tt $char2:tt $char3:tt) => { + pub fn $name(tokens: &mut TokenStream, span: Span) { + let mut punct = Punct::new($char1, Spacing::Joint); + punct.set_span(span); + tokens.append(punct); + let mut punct = Punct::new($char2, Spacing::Joint); + punct.set_span(span); + tokens.append(punct); + let mut punct = Punct::new($char3, Spacing::Alone); + punct.set_span(span); + tokens.append(punct); + } + }; +} + +push_punct!(push_add '+'); +push_punct!(push_add_eq '+' '='); +push_punct!(push_and '&'); +push_punct!(push_and_and '&' '&'); +push_punct!(push_and_eq '&' '='); +push_punct!(push_at '@'); +push_punct!(push_bang '!'); +push_punct!(push_caret '^'); +push_punct!(push_caret_eq '^' '='); +push_punct!(push_colon ':'); +push_punct!(push_colon2 ':' ':'); +push_punct!(push_comma ','); +push_punct!(push_div '/'); +push_punct!(push_div_eq '/' '='); +push_punct!(push_dot '.'); +push_punct!(push_dot2 '.' '.'); +push_punct!(push_dot3 '.' '.' '.'); +push_punct!(push_dot_dot_eq '.' '.' '='); +push_punct!(push_eq '='); +push_punct!(push_eq_eq '=' '='); +push_punct!(push_ge '>' '='); +push_punct!(push_gt '>'); +push_punct!(push_le '<' '='); +push_punct!(push_lt '<'); +push_punct!(push_mul_eq '*' '='); +push_punct!(push_ne '!' '='); +push_punct!(push_or '|'); +push_punct!(push_or_eq '|' '='); +push_punct!(push_or_or '|' '|'); +push_punct!(push_pound '#'); +push_punct!(push_question '?'); +push_punct!(push_rarrow '-' '>'); +push_punct!(push_larrow '<' '-'); +push_punct!(push_rem '%'); +push_punct!(push_rem_eq '%' '='); +push_punct!(push_fat_arrow '=' '>'); +push_punct!(push_semi ';'); +push_punct!(push_shl '<' '<'); +push_punct!(push_shl_eq '<' '<' '='); +push_punct!(push_shr '>' '>'); +push_punct!(push_shr_eq '>' '>' '='); +push_punct!(push_star '*'); +push_punct!(push_sub '-'); +push_punct!(push_sub_eq '-' '='); diff --git a/vendor/quote/src/to_tokens.rs b/vendor/quote/src/to_tokens.rs index 4a9c8f11ec..9d221b27b6 100644 --- a/vendor/quote/src/to_tokens.rs +++ b/vendor/quote/src/to_tokens.rs @@ -2,6 +2,7 @@ use super::TokenStreamExt; use std::borrow::Cow; use std::iter; +use std::rc::Rc; use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree}; @@ -21,12 +22,9 @@ pub trait ToTokens { /// Example implementation for a struct representing Rust paths like /// `std::cmp::PartialEq`: /// - /// ``` - /// extern crate quote; - /// use quote::{TokenStreamExt, ToTokens}; - /// - /// extern crate proc_macro2; + /// ```edition2018 /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream}; + /// use quote::{TokenStreamExt, ToTokens}; /// /// pub struct Path { /// pub global: bool, @@ -53,8 +51,6 @@ pub trait ToTokens { /// # unimplemented!() /// # } /// # } - /// # - /// # fn main() {} /// ``` fn to_tokens(&self, tokens: &mut TokenStream); @@ -96,6 +92,12 @@ impl ToTokens for Box { } } +impl ToTokens for Rc { + fn to_tokens(&self, tokens: &mut TokenStream) { + (**self).to_tokens(tokens); + } +} + impl ToTokens for Option { fn to_tokens(&self, tokens: &mut TokenStream) { if let Some(ref t) = *self { diff --git a/vendor/rand-0.4.3/.cargo-checksum.json b/vendor/rand-0.4.6/.cargo-checksum.json similarity index 80% rename from vendor/rand-0.4.3/.cargo-checksum.json rename to vendor/rand-0.4.6/.cargo-checksum.json index 824131b10b..56e791669c 100644 --- a/vendor/rand-0.4.3/.cargo-checksum.json +++ b/vendor/rand-0.4.6/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"460c7dbfdf227b4c725f7da8131fd51a54d0355b3c5804c0d388c70d3c1c49ec","Cargo.toml":"7d29da51fe4bf73964b3b3dea0af88040514569e2d184c9e8eb2f1746d540fb7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"fb8071c3bc1013107b16ebcb303f31ef614e81440f2d58a46bfb9ff1e311b792","appveyor.yml":"8796156caf7041ef2a43f7a313df21ea639de3f2563b6181bba1096b1c489f1b","benches/bench.rs":"35c4ab609f2a5f5aab6c52c257415258dc0780621b492b5a82bb12d048cab6db","benches/distributions/exponential.rs":"99cb59c013a0b6bb390d34c5649b341fc3b88ea7df0caf2470bdda8798f9fe3d","benches/distributions/gamma.rs":"3533f311e4b55d743c5b01a7eb6529c94fd97726ef6702a6372f914f5f33666b","benches/distributions/mod.rs":"0028f1cb96f61152ed5b49a4fe91227d809ef6d19035592c36032a538af7f95e","benches/distributions/normal.rs":"4e10c18cb583ccb96301ea953c8e0aa9ee3b6662060271d1b8d19ca23364dc6b","benches/generators.rs":"aaa2f1dbfb399df8323d8a5796b92add6210cd5f0f1d916895ffdd81d60f812b","benches/misc.rs":"bd2f7c5a16f0fcb59022d5aeef66ed3c94e89ebf6c06667851dd23d0b1595504","src/distributions/exponential.rs":"103c8412c8a581b71835f1c00e40f6370e7702adf9d499243933a793d132d4e7","src/distributions/gamma.rs":"7a3f85c8daad4e56e334586ddb9fc9d83df3b0699738ed681a6c41e4ed455be9","src/distributions/mod.rs":"7943c4f83721bac816f831cca3b1574b6136932f7b4927aa6101130080ba62c5","src/distributions/normal.rs":"1562b43f80e4d5f83a8deb5af18de5a18dfeeeeda11fefc577da26672b14c949","src/distributions/range.rs":"a72a538d3ec4ed23f8d632aa55fd4793c464f24a5872d04ce8095ddd5db92115","src/distributions/ziggurat_tables.rs":"4eacf94fc352c91c455a6623de6a721e53842e1690f13a5662b6a79c7fbb73de","src/jitter.rs":"befd4b84bf753c107370b5b9498ad49611c220bdae2e4be9ee4398e9fa497042","src/lib.rs":"fbdc5f56ce1a52b15c85b0aa70a555c64be8f65d9f6f90fa0a3555d7862666b4","src/os.rs":"4860f165f68b7c978b0488c75d264cd9aaf54e7e4484036736ee5c4f5b6bd78d","src/prng/chacha.rs":"558007276f9c22933d39e5b8e853f4dd9533e823ed66df8dc1f23ad6925b1d51","src/prng/isaac.rs":"a8a2ee8b38d312663308e3bdf03376e342fd91330655f39144e5bba7392b2a8e","src/prng/isaac64.rs":"f28f7596ccab910db265b42671116abb9d2039fa8a421cbc75312bd0e7715d3a","src/prng/mod.rs":"c1a73450f49e819a20942a5b591f84a08ebb5ac33aa0f65b18ac1dc9a19a3084","src/prng/xorshift.rs":"606c308747293652c868b46dc3cad847d0c3717629c04ba75681c887c7634114","src/rand_impls.rs":"e1f27077fc13d5855bb66235f8ccfb216e116337eb38424d9c30c090e112215c","src/read.rs":"bd0eb508a6b659dc578d546fc2f231484aed80c73cfe8c475e0d65c8d699a769","src/reseeding.rs":"a97b86387b87ea1adc5262ddea480fe735c9c2a86762abaace29119022ac9f6e","src/seq.rs":"76dd58af0f580aed2721c393a5c036322186dc7cb3b4abed33436620c7c49288","utils/ziggurat_tables.py":"a9fc0a2fdae9b5c798c238788f94b720c156e13fd96f2356c409aa533191eb94"},"package":"8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"} \ No newline at end of file +{"files":{"CHANGELOG.md":"f5e9c71d4123971f9f6c54eed8837245e6cac4b610c9d23b680fa95538946142","Cargo.toml":"4c770ee471e19f4a453a36d76479f9a530987058b793c735cd7a2bcf937d7edb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"fb8071c3bc1013107b16ebcb303f31ef614e81440f2d58a46bfb9ff1e311b792","appveyor.yml":"8796156caf7041ef2a43f7a313df21ea639de3f2563b6181bba1096b1c489f1b","benches/bench.rs":"35c4ab609f2a5f5aab6c52c257415258dc0780621b492b5a82bb12d048cab6db","benches/distributions/exponential.rs":"99cb59c013a0b6bb390d34c5649b341fc3b88ea7df0caf2470bdda8798f9fe3d","benches/distributions/gamma.rs":"3533f311e4b55d743c5b01a7eb6529c94fd97726ef6702a6372f914f5f33666b","benches/distributions/mod.rs":"0028f1cb96f61152ed5b49a4fe91227d809ef6d19035592c36032a538af7f95e","benches/distributions/normal.rs":"4e10c18cb583ccb96301ea953c8e0aa9ee3b6662060271d1b8d19ca23364dc6b","benches/generators.rs":"aaa2f1dbfb399df8323d8a5796b92add6210cd5f0f1d916895ffdd81d60f812b","benches/misc.rs":"bd2f7c5a16f0fcb59022d5aeef66ed3c94e89ebf6c06667851dd23d0b1595504","src/distributions/exponential.rs":"103c8412c8a581b71835f1c00e40f6370e7702adf9d499243933a793d132d4e7","src/distributions/gamma.rs":"7a3f85c8daad4e56e334586ddb9fc9d83df3b0699738ed681a6c41e4ed455be9","src/distributions/mod.rs":"7943c4f83721bac816f831cca3b1574b6136932f7b4927aa6101130080ba62c5","src/distributions/normal.rs":"1562b43f80e4d5f83a8deb5af18de5a18dfeeeeda11fefc577da26672b14c949","src/distributions/range.rs":"a72a538d3ec4ed23f8d632aa55fd4793c464f24a5872d04ce8095ddd5db92115","src/distributions/ziggurat_tables.rs":"4eacf94fc352c91c455a6623de6a721e53842e1690f13a5662b6a79c7fbb73de","src/jitter.rs":"befd4b84bf753c107370b5b9498ad49611c220bdae2e4be9ee4398e9fa497042","src/lib.rs":"f9f4d15c2ce67f9ba21261a4bc76599523b930698cee2ae1e37d01f0d2ba834e","src/os.rs":"bbba4481432ae0f19bafb2168af5e7e1a858547ff8a7f8996286ea1b2a951158","src/prng/chacha.rs":"558007276f9c22933d39e5b8e853f4dd9533e823ed66df8dc1f23ad6925b1d51","src/prng/isaac.rs":"a8a2ee8b38d312663308e3bdf03376e342fd91330655f39144e5bba7392b2a8e","src/prng/isaac64.rs":"f28f7596ccab910db265b42671116abb9d2039fa8a421cbc75312bd0e7715d3a","src/prng/mod.rs":"c1a73450f49e819a20942a5b591f84a08ebb5ac33aa0f65b18ac1dc9a19a3084","src/prng/xorshift.rs":"606c308747293652c868b46dc3cad847d0c3717629c04ba75681c887c7634114","src/rand_impls.rs":"e1f27077fc13d5855bb66235f8ccfb216e116337eb38424d9c30c090e112215c","src/read.rs":"bd0eb508a6b659dc578d546fc2f231484aed80c73cfe8c475e0d65c8d699a769","src/reseeding.rs":"a97b86387b87ea1adc5262ddea480fe735c9c2a86762abaace29119022ac9f6e","src/seq.rs":"76dd58af0f580aed2721c393a5c036322186dc7cb3b4abed33436620c7c49288","utils/ziggurat_tables.py":"a9fc0a2fdae9b5c798c238788f94b720c156e13fd96f2356c409aa533191eb94"},"package":"552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"} \ No newline at end of file diff --git a/vendor/rand-0.4.3/CHANGELOG.md b/vendor/rand-0.4.6/CHANGELOG.md similarity index 97% rename from vendor/rand-0.4.3/CHANGELOG.md rename to vendor/rand-0.4.6/CHANGELOG.md index 1811b458fb..aa4c293747 100644 --- a/vendor/rand-0.4.3/CHANGELOG.md +++ b/vendor/rand-0.4.6/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.4.5] - 2019-01-25 +### Platforms +- Fuchsia: Replaced fuchsia-zircon with fuchsia-cprng + +## [0.4.4] - 2019-01-06 +### Added +- SGX support + ## [0.4.3] - 2018-08-16 ### Fixed - Use correct syscall number for PowerPC (#589) diff --git a/vendor/rand-0.4.3/Cargo.toml b/vendor/rand-0.4.6/Cargo.toml similarity index 81% rename from vendor/rand-0.4.3/Cargo.toml rename to vendor/rand-0.4.6/Cargo.toml index 4f80003e44..64d240c65c 100644 --- a/vendor/rand-0.4.3/Cargo.toml +++ b/vendor/rand-0.4.6/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "rand" -version = "0.4.3" +version = "0.4.6" authors = ["The Rust Project Developers"] description = "Random number generators and other randomness functionality.\n" homepage = "https://github.com/rust-lang-nursery/rand" @@ -29,8 +29,14 @@ default = ["std"] i128_support = [] nightly = ["i128_support"] std = ["libc"] -[target."cfg(target_os = \"fuchsia\")".dependencies.fuchsia-zircon] -version = "0.3.2" +[target."cfg(target_env = \"sgx\")".dependencies.rand_core] +version = "0.3" +default-features = false + +[target."cfg(target_env = \"sgx\")".dependencies.rdrand] +version = "0.4.0" +[target."cfg(target_os = \"fuchsia\")".dependencies.fuchsia-cprng] +version = "0.1.0" [target."cfg(unix)".dependencies.libc] version = "0.2" optional = true diff --git a/vendor/rand-0.4.6/LICENSE-APACHE b/vendor/rand-0.4.6/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/vendor/rand-0.4.6/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/rand-0.4.3/LICENSE-MIT b/vendor/rand-0.4.6/LICENSE-MIT similarity index 100% rename from vendor/rand-0.4.3/LICENSE-MIT rename to vendor/rand-0.4.6/LICENSE-MIT diff --git a/vendor/rand-0.4.3/README.md b/vendor/rand-0.4.6/README.md similarity index 100% rename from vendor/rand-0.4.3/README.md rename to vendor/rand-0.4.6/README.md diff --git a/vendor/rand-0.4.3/appveyor.yml b/vendor/rand-0.4.6/appveyor.yml similarity index 100% rename from vendor/rand-0.4.3/appveyor.yml rename to vendor/rand-0.4.6/appveyor.yml diff --git a/vendor/rand-0.4.3/benches/bench.rs b/vendor/rand-0.4.6/benches/bench.rs similarity index 100% rename from vendor/rand-0.4.3/benches/bench.rs rename to vendor/rand-0.4.6/benches/bench.rs diff --git a/vendor/rand-0.4.3/benches/distributions/exponential.rs b/vendor/rand-0.4.6/benches/distributions/exponential.rs similarity index 100% rename from vendor/rand-0.4.3/benches/distributions/exponential.rs rename to vendor/rand-0.4.6/benches/distributions/exponential.rs diff --git a/vendor/rand-0.4.3/benches/distributions/gamma.rs b/vendor/rand-0.4.6/benches/distributions/gamma.rs similarity index 100% rename from vendor/rand-0.4.3/benches/distributions/gamma.rs rename to vendor/rand-0.4.6/benches/distributions/gamma.rs diff --git a/vendor/rand-0.4.3/benches/distributions/mod.rs b/vendor/rand-0.4.6/benches/distributions/mod.rs similarity index 100% rename from vendor/rand-0.4.3/benches/distributions/mod.rs rename to vendor/rand-0.4.6/benches/distributions/mod.rs diff --git a/vendor/rand-0.4.3/benches/distributions/normal.rs b/vendor/rand-0.4.6/benches/distributions/normal.rs similarity index 100% rename from vendor/rand-0.4.3/benches/distributions/normal.rs rename to vendor/rand-0.4.6/benches/distributions/normal.rs diff --git a/vendor/rand-0.4.3/benches/generators.rs b/vendor/rand-0.4.6/benches/generators.rs similarity index 100% rename from vendor/rand-0.4.3/benches/generators.rs rename to vendor/rand-0.4.6/benches/generators.rs diff --git a/vendor/rand-0.4.3/benches/misc.rs b/vendor/rand-0.4.6/benches/misc.rs similarity index 100% rename from vendor/rand-0.4.3/benches/misc.rs rename to vendor/rand-0.4.6/benches/misc.rs diff --git a/vendor/rand-0.4.3/src/distributions/exponential.rs b/vendor/rand-0.4.6/src/distributions/exponential.rs similarity index 100% rename from vendor/rand-0.4.3/src/distributions/exponential.rs rename to vendor/rand-0.4.6/src/distributions/exponential.rs diff --git a/vendor/rand-0.4.3/src/distributions/gamma.rs b/vendor/rand-0.4.6/src/distributions/gamma.rs similarity index 100% rename from vendor/rand-0.4.3/src/distributions/gamma.rs rename to vendor/rand-0.4.6/src/distributions/gamma.rs diff --git a/vendor/rand-0.4.3/src/distributions/mod.rs b/vendor/rand-0.4.6/src/distributions/mod.rs similarity index 100% rename from vendor/rand-0.4.3/src/distributions/mod.rs rename to vendor/rand-0.4.6/src/distributions/mod.rs diff --git a/vendor/rand-0.4.3/src/distributions/normal.rs b/vendor/rand-0.4.6/src/distributions/normal.rs similarity index 100% rename from vendor/rand-0.4.3/src/distributions/normal.rs rename to vendor/rand-0.4.6/src/distributions/normal.rs diff --git a/vendor/rand-0.4.3/src/distributions/range.rs b/vendor/rand-0.4.6/src/distributions/range.rs similarity index 100% rename from vendor/rand-0.4.3/src/distributions/range.rs rename to vendor/rand-0.4.6/src/distributions/range.rs diff --git a/vendor/rand-0.4.3/src/distributions/ziggurat_tables.rs b/vendor/rand-0.4.6/src/distributions/ziggurat_tables.rs similarity index 100% rename from vendor/rand-0.4.3/src/distributions/ziggurat_tables.rs rename to vendor/rand-0.4.6/src/distributions/ziggurat_tables.rs diff --git a/vendor/rand-0.4.3/src/jitter.rs b/vendor/rand-0.4.6/src/jitter.rs similarity index 100% rename from vendor/rand-0.4.3/src/jitter.rs rename to vendor/rand-0.4.6/src/jitter.rs diff --git a/vendor/rand-0.4.3/src/lib.rs b/vendor/rand-0.4.6/src/lib.rs similarity index 99% rename from vendor/rand-0.4.3/src/lib.rs rename to vendor/rand-0.4.6/src/lib.rs index 7b22dd45de..696ff6fd5e 100644 --- a/vendor/rand-0.4.3/src/lib.rs +++ b/vendor/rand-0.4.6/src/lib.rs @@ -250,6 +250,12 @@ #[cfg(feature="std")] extern crate std as core; #[cfg(all(feature = "alloc", not(feature="std")))] extern crate alloc; +#[cfg(target_env = "sgx")] +extern crate rdrand; + +#[cfg(target_env = "sgx")] +extern crate rand_core; + use core::marker; use core::mem; #[cfg(feature="std")] use std::cell::RefCell; diff --git a/vendor/rand-0.4.3/src/os.rs b/vendor/rand-0.4.6/src/os.rs similarity index 92% rename from vendor/rand-0.4.3/src/os.rs rename to vendor/rand-0.4.6/src/os.rs index 10022fbcd6..c33a8cbfca 100644 --- a/vendor/rand-0.4.3/src/os.rs +++ b/vendor/rand-0.4.6/src/os.rs @@ -11,7 +11,11 @@ //! Interfaces to the operating system provided random number //! generators. -use std::{io, mem, fmt}; +use std::{io, fmt}; + +#[cfg(not(target_env = "sgx"))] +use std::mem; + use Rng; /// A random number generator that retrieves randomness straight from @@ -53,12 +57,14 @@ impl fmt::Debug for OsRng { } } +#[cfg(not(target_env = "sgx"))] fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 { let mut buf: [u8; 4] = [0; 4]; fill_buf(&mut buf); unsafe { mem::transmute::<[u8; 4], u32>(buf) } } +#[cfg(not(target_env = "sgx"))] fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 { let mut buf: [u8; 8] = [0; 8]; fill_buf(&mut buf); @@ -383,7 +389,7 @@ mod imp { #[cfg(target_os = "fuchsia")] mod imp { - extern crate fuchsia_zircon; + extern crate fuchsia_cprng; use std::io; use Rng; @@ -407,15 +413,7 @@ mod imp { next_u64(&mut |v| self.fill_bytes(v)) } fn fill_bytes(&mut self, v: &mut [u8]) { - for s in v.chunks_mut(fuchsia_zircon::sys::ZX_CPRNG_DRAW_MAX_LEN) { - let mut filled = 0; - while filled < s.len() { - match fuchsia_zircon::cprng_draw(&mut s[filled..]) { - Ok(actual) => filled += actual, - Err(e) => panic!("cprng_draw failed: {:?}", e), - }; - } - } + fuchsia_cprng::cprng_draw(v); } } } @@ -562,6 +560,47 @@ mod imp { } } +#[cfg(target_env = "sgx")] +mod imp { + use rdrand::RdRand; + use std::io; + use rand_core::RngCore; + + pub struct OsRng{ + gen: RdRand + } + + impl OsRng { + pub fn new() -> io::Result { + match RdRand::new() { + Ok(rng) => Ok(OsRng { gen: rng }), + Err(_) => Err(io::Error::new(io::ErrorKind::Other, "Not supported")) + } + } + + pub(crate) fn next_u32(&mut self) -> u32 { + match self.gen.try_next_u32() { + Some(n) => n, + None => panic!("Non-recoverable hardware failure has occured") + } + } + + pub(crate) fn next_u64(&mut self) -> u64 { + match self.gen.try_next_u64() { + Some(n) => n, + None => panic!("Non-recoverable hardware failure has occured") + } + } + + pub(crate) fn fill_bytes(&mut self, v: &mut [u8]) { + match self.gen.try_fill_bytes(v) { + Ok(_) => {}, + Err(_) => panic!("Non-recoverable hardware failure has occured") + } + } + } +} + #[cfg(test)] mod test { use std::sync::mpsc::channel; diff --git a/vendor/rand-0.4.3/src/prng/chacha.rs b/vendor/rand-0.4.6/src/prng/chacha.rs similarity index 100% rename from vendor/rand-0.4.3/src/prng/chacha.rs rename to vendor/rand-0.4.6/src/prng/chacha.rs diff --git a/vendor/rand-0.4.3/src/prng/isaac.rs b/vendor/rand-0.4.6/src/prng/isaac.rs similarity index 100% rename from vendor/rand-0.4.3/src/prng/isaac.rs rename to vendor/rand-0.4.6/src/prng/isaac.rs diff --git a/vendor/rand-0.4.3/src/prng/isaac64.rs b/vendor/rand-0.4.6/src/prng/isaac64.rs similarity index 100% rename from vendor/rand-0.4.3/src/prng/isaac64.rs rename to vendor/rand-0.4.6/src/prng/isaac64.rs diff --git a/vendor/rand-0.4.3/src/prng/mod.rs b/vendor/rand-0.4.6/src/prng/mod.rs similarity index 100% rename from vendor/rand-0.4.3/src/prng/mod.rs rename to vendor/rand-0.4.6/src/prng/mod.rs diff --git a/vendor/rand-0.4.3/src/prng/xorshift.rs b/vendor/rand-0.4.6/src/prng/xorshift.rs similarity index 100% rename from vendor/rand-0.4.3/src/prng/xorshift.rs rename to vendor/rand-0.4.6/src/prng/xorshift.rs diff --git a/vendor/rand-0.4.3/src/rand_impls.rs b/vendor/rand-0.4.6/src/rand_impls.rs similarity index 100% rename from vendor/rand-0.4.3/src/rand_impls.rs rename to vendor/rand-0.4.6/src/rand_impls.rs diff --git a/vendor/rand-0.4.3/src/read.rs b/vendor/rand-0.4.6/src/read.rs similarity index 100% rename from vendor/rand-0.4.3/src/read.rs rename to vendor/rand-0.4.6/src/read.rs diff --git a/vendor/rand-0.4.3/src/reseeding.rs b/vendor/rand-0.4.6/src/reseeding.rs similarity index 100% rename from vendor/rand-0.4.3/src/reseeding.rs rename to vendor/rand-0.4.6/src/reseeding.rs diff --git a/vendor/rand-0.4.3/src/seq.rs b/vendor/rand-0.4.6/src/seq.rs similarity index 100% rename from vendor/rand-0.4.3/src/seq.rs rename to vendor/rand-0.4.6/src/seq.rs diff --git a/vendor/rand-0.4.3/utils/ziggurat_tables.py b/vendor/rand-0.4.6/utils/ziggurat_tables.py similarity index 100% rename from vendor/rand-0.4.3/utils/ziggurat_tables.py rename to vendor/rand-0.4.6/utils/ziggurat_tables.py diff --git a/vendor/rand_core/.cargo-checksum.json b/vendor/rand_core-0.3.0/.cargo-checksum.json similarity index 100% rename from vendor/rand_core/.cargo-checksum.json rename to vendor/rand_core-0.3.0/.cargo-checksum.json diff --git a/vendor/rand_core/CHANGELOG.md b/vendor/rand_core-0.3.0/CHANGELOG.md similarity index 100% rename from vendor/rand_core/CHANGELOG.md rename to vendor/rand_core-0.3.0/CHANGELOG.md diff --git a/vendor/rand_core/COPYRIGHT b/vendor/rand_core-0.3.0/COPYRIGHT similarity index 100% rename from vendor/rand_core/COPYRIGHT rename to vendor/rand_core-0.3.0/COPYRIGHT diff --git a/vendor/rand_core/Cargo.toml b/vendor/rand_core-0.3.0/Cargo.toml similarity index 100% rename from vendor/rand_core/Cargo.toml rename to vendor/rand_core-0.3.0/Cargo.toml diff --git a/vendor/rand_core/LICENSE-APACHE b/vendor/rand_core-0.3.0/LICENSE-APACHE similarity index 100% rename from vendor/rand_core/LICENSE-APACHE rename to vendor/rand_core-0.3.0/LICENSE-APACHE diff --git a/vendor/rand_core/LICENSE-MIT b/vendor/rand_core-0.3.0/LICENSE-MIT similarity index 100% rename from vendor/rand_core/LICENSE-MIT rename to vendor/rand_core-0.3.0/LICENSE-MIT diff --git a/vendor/rand_core/README.md b/vendor/rand_core-0.3.0/README.md similarity index 100% rename from vendor/rand_core/README.md rename to vendor/rand_core-0.3.0/README.md diff --git a/vendor/rand_core/src/block.rs b/vendor/rand_core-0.3.0/src/block.rs similarity index 100% rename from vendor/rand_core/src/block.rs rename to vendor/rand_core-0.3.0/src/block.rs diff --git a/vendor/rand_core/src/error.rs b/vendor/rand_core-0.3.0/src/error.rs similarity index 100% rename from vendor/rand_core/src/error.rs rename to vendor/rand_core-0.3.0/src/error.rs diff --git a/vendor/rand_core/src/impls.rs b/vendor/rand_core-0.3.0/src/impls.rs similarity index 100% rename from vendor/rand_core/src/impls.rs rename to vendor/rand_core-0.3.0/src/impls.rs diff --git a/vendor/rand_core/src/le.rs b/vendor/rand_core-0.3.0/src/le.rs similarity index 100% rename from vendor/rand_core/src/le.rs rename to vendor/rand_core-0.3.0/src/le.rs diff --git a/vendor/rand_core/src/lib.rs b/vendor/rand_core-0.3.0/src/lib.rs similarity index 100% rename from vendor/rand_core/src/lib.rs rename to vendor/rand_core-0.3.0/src/lib.rs diff --git a/vendor/rayon-core/.cargo-checksum.json b/vendor/rayon-core/.cargo-checksum.json index 5e41ec3553..9957a273ec 100644 --- a/vendor/rayon-core/.cargo-checksum.json +++ b/vendor/rayon-core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"34b1cbb8413751b716444269a455b294228fd6cf4fb3f95c849182e12fead815","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"32b5268c63c55d843735b93d6b755279b1e9f7dd7f45d34bbe24effb27d9f674","build.rs":"fa31cb198b772600d100a7c403ddedccef637d2e6b2da431fa7f02ca41307fc6","src/internal/mod.rs":"26fb298bbb0d785bae5da8ca181b02f267376e766cea0757a191136fc432103e","src/internal/task.rs":"0aafd209e52fdf34c544487cea3e3b46a51a5b8b2651534f2902458c44e621d4","src/internal/worker.rs":"94fd86908128dd500a476bc635ff67f50363153aab38ad675136967fe5cd45f4","src/job.rs":"6ada245db21c326657278cc55caf927e8fb4f8c1c5b74154c33e395a3d9ce99d","src/join/mod.rs":"4b0395f66c0ea23e6b54ac62b646697fa07bc3bde548efb9b57128ede900a546","src/join/test.rs":"774f6330024cbb9d896345b07da57bc545c877cf5a03de26903c8f718d388765","src/latch.rs":"cec40108c5bd33b1db6b23af2974edda05d9a38518c0e5bd0481bfb2fd0ac82d","src/lib.rs":"424673b805538cac3c0576dca92c12e246bcf04faa7cfd938ef3634a4ee9e1f9","src/log.rs":"95fcb9c0613bb5fc865b5a74bf0300df54ca08e406b05a5fa7e09cb8eb526a9a","src/registry.rs":"f2aeb1f866cdc4a65356cff63862cfd681f7ba87ea96989ab846ae0fd74a1684","src/scope/internal.rs":"63103af40d09fc544d9b757ef48cdf8f2fe8b5e05962cbf98783e18f2314ca9c","src/scope/mod.rs":"55a5b991bf5ff7a0a7e9ac44f89ba7a59f9bac9e2d7085b3de30a09b8ca57707","src/scope/test.rs":"a15d3d31299d05333e83975d67eba37d7a6dd4dd85452bad0ed159382455335e","src/sleep/README.md":"34a83cd8a0f84e58472af5c40744794139fbfe22a392f0dc6eb90cfdf9389119","src/sleep/mod.rs":"f5e5caf619a23da6534d69fff7beb7f4c361bd5b8d86e81e6326eab300e1507c","src/spawn/mod.rs":"7665de0682ae4d232d0f2db70f64dfd330bf400c8b17a70ecb165c8dcd6a7070","src/spawn/test.rs":"39073aa2c0f933997fa32a723ef0acbd7b1236e4d839471eec0e6103a894d8bb","src/test.rs":"8b7bc544fb6f853e99d42bbb8b1a77b6b5bc31de16a127c54f9e005f2b7b1e97","src/thread_pool/internal.rs":"eb64a10ef3d52f5eebb7ac7a0023c557bbdb52cb0ab412aa3eba265b60628c8e","src/thread_pool/mod.rs":"867f57a2bbe8c18e879eb509c285f70cbf0ef3310dc5119394f2edaaaab2f144","src/thread_pool/test.rs":"14e7214584b49c1cf2cdaa174b49b4eae4dc8a3d96df45b4ee5e9a3671ea0e6f","src/unwind.rs":"23c7dcc38524f61193b36f371b4ed918aa2e67ed0e155788d09f7eb5fcd4b6bd","src/util.rs":"63ec7e1c75ea3871593d7fa5fc46689de7a2a86aa080b587880181dafd5e9838"},"package":"9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"} \ No newline at end of file +{"files":{"Cargo.toml":"1a43bafac19c6935e206e3baae16b7f71e13291fb419f8804d123848fe10dce0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"32b5268c63c55d843735b93d6b755279b1e9f7dd7f45d34bbe24effb27d9f674","build.rs":"fa31cb198b772600d100a7c403ddedccef637d2e6b2da431fa7f02ca41307fc6","src/compile_fail/mod.rs":"3e4421ca786eb08934ed0c4329a4eb986de9760967c587610f23c0271ec42441","src/compile_fail/quicksort_race1.rs":"35f498cda38f4eb6e00117f78ed68e0fe5a3fa61c25303d9c08a19bda345bc6c","src/compile_fail/quicksort_race2.rs":"cbb40030c7867cae34bb373b6ec5d97c2ac6de39bc917f47879b30eb423924bc","src/compile_fail/quicksort_race3.rs":"8403643e64c969306b1a9b1243378e6ccdd313b57e1878dbd31393618082fd35","src/compile_fail/rc_return.rs":"b6f1f821ef30086e2990db1ac58a92adaf31e57c23c587c7746d6303865c5c0f","src/compile_fail/rc_upvar.rs":"92a799b313fb88a0eb83fc1aaaea4b61604222b45e20f1c22ff5b092a03f8620","src/compile_fail/scope_join_bad.rs":"7ce5355823be9c01dd6ddf1da110b3cff1092a025788f6f6c58cbd21bd09c8ad","src/internal/mod.rs":"26fb298bbb0d785bae5da8ca181b02f267376e766cea0757a191136fc432103e","src/internal/task.rs":"0aafd209e52fdf34c544487cea3e3b46a51a5b8b2651534f2902458c44e621d4","src/internal/worker.rs":"94fd86908128dd500a476bc635ff67f50363153aab38ad675136967fe5cd45f4","src/job.rs":"6ada245db21c326657278cc55caf927e8fb4f8c1c5b74154c33e395a3d9ce99d","src/join/mod.rs":"ec2d540ae6054f519c3a25f38fe2b27b9a4c7ce6fbaabeef5cd853eeb6f4a139","src/join/test.rs":"ce9e8ab67135af1099672eb058e18c0e68e179e627235d2a2cab4e5c1050010e","src/latch.rs":"cec40108c5bd33b1db6b23af2974edda05d9a38518c0e5bd0481bfb2fd0ac82d","src/lib.rs":"92c93c71d5c9a5c80687d635163dffafd6b7fe361acdc83bf8de0058466c7017","src/log.rs":"95fcb9c0613bb5fc865b5a74bf0300df54ca08e406b05a5fa7e09cb8eb526a9a","src/registry.rs":"7f06b0f7412b58c0d4e969764f9b8058d06793b2bc14d3d71156184415cc2c59","src/scope/internal.rs":"63103af40d09fc544d9b757ef48cdf8f2fe8b5e05962cbf98783e18f2314ca9c","src/scope/mod.rs":"55a5b991bf5ff7a0a7e9ac44f89ba7a59f9bac9e2d7085b3de30a09b8ca57707","src/scope/test.rs":"f57d58a59f7e6b8bec07cdf57525a5ed8acf72eb228f4bb161cf7e73f6595fcb","src/sleep/README.md":"34a83cd8a0f84e58472af5c40744794139fbfe22a392f0dc6eb90cfdf9389119","src/sleep/mod.rs":"f5e5caf619a23da6534d69fff7beb7f4c361bd5b8d86e81e6326eab300e1507c","src/spawn/mod.rs":"7665de0682ae4d232d0f2db70f64dfd330bf400c8b17a70ecb165c8dcd6a7070","src/spawn/test.rs":"39073aa2c0f933997fa32a723ef0acbd7b1236e4d839471eec0e6103a894d8bb","src/test.rs":"8b7bc544fb6f853e99d42bbb8b1a77b6b5bc31de16a127c54f9e005f2b7b1e97","src/thread_pool/internal.rs":"eb64a10ef3d52f5eebb7ac7a0023c557bbdb52cb0ab412aa3eba265b60628c8e","src/thread_pool/mod.rs":"867f57a2bbe8c18e879eb509c285f70cbf0ef3310dc5119394f2edaaaab2f144","src/thread_pool/test.rs":"14e7214584b49c1cf2cdaa174b49b4eae4dc8a3d96df45b4ee5e9a3671ea0e6f","src/unwind.rs":"23c7dcc38524f61193b36f371b4ed918aa2e67ed0e155788d09f7eb5fcd4b6bd","src/util.rs":"63ec7e1c75ea3871593d7fa5fc46689de7a2a86aa080b587880181dafd5e9838","tests/double_init_fail.rs":"ca6d02537985196e6c4d2a851b8eb3011b7ae2c5b6c10d6af49b18834914c26b","tests/init_zero_threads.rs":"f3488078776b5866249fc198d6e44853ef55a739ddf552bbc655b7ca7d990862","tests/scope_join.rs":"53de4c5cdacf54d45c9955fbb36b7a95b2f2adbaae16ed4c194342cda29ed43d","tests/simple_panic.rs":"2e3a9ad0160c2bd49782240258f3a7d8483b7811c524739f0e390c28ea40bc30","tests/stack_overflow_crash.rs":"669a7d5e7e9162da83f5350fb80c3d6d65feae965e67f8905b920d49d5bdde15"},"package":"b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"} \ No newline at end of file diff --git a/vendor/rayon-core/Cargo.toml b/vendor/rayon-core/Cargo.toml index a96bf4efef..2071468add 100644 --- a/vendor/rayon-core/Cargo.toml +++ b/vendor/rayon-core/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "rayon-core" -version = "1.4.0" +version = "1.4.1" authors = ["Niko Matsakis ", "Josh Stone "] build = "build.rs" links = "rayon-core" @@ -23,6 +23,27 @@ keywords = ["parallel", "thread", "concurrency", "join", "performance"] categories = ["concurrency"] license = "Apache-2.0/MIT" repository = "https://github.com/rayon-rs/rayon" + +[[test]] +name = "stack_overflow_crash" +path = "tests/stack_overflow_crash.rs" +harness = false + +[[test]] +name = "double_init_fail" +path = "tests/double_init_fail.rs" + +[[test]] +name = "init_zero_threads" +path = "tests/init_zero_threads.rs" + +[[test]] +name = "scope_join" +path = "tests/scope_join.rs" + +[[test]] +name = "simple_panic" +path = "tests/simple_panic.rs" [dependencies.crossbeam-deque] version = "0.2.0" @@ -34,8 +55,5 @@ version = "0.2.16" [dependencies.num_cpus] version = "1.2" - -[dependencies.rand] -version = ">= 0.3, < 0.5" - -[dev-dependencies] +[dev-dependencies.rand] +version = "0.5" diff --git a/vendor/rayon-core/src/compile_fail/mod.rs b/vendor/rayon-core/src/compile_fail/mod.rs new file mode 100644 index 0000000000..d58cbcc9d5 --- /dev/null +++ b/vendor/rayon-core/src/compile_fail/mod.rs @@ -0,0 +1,8 @@ + +// These modules contain `compile_fail` doc tests. +mod quicksort_race1; +mod quicksort_race2; +mod quicksort_race3; +mod rc_return; +mod rc_upvar; +mod scope_join_bad; diff --git a/vendor/rayon-core/src/compile_fail/quicksort_race1.rs b/vendor/rayon-core/src/compile_fail/quicksort_race1.rs new file mode 100644 index 0000000000..5615033895 --- /dev/null +++ b/vendor/rayon-core/src/compile_fail/quicksort_race1.rs @@ -0,0 +1,28 @@ +/*! ```compile_fail,E0524 + +fn quick_sort(v: &mut [T]) { + if v.len() <= 1 { + return; + } + + let mid = partition(v); + let (lo, _hi) = v.split_at_mut(mid); + rayon_core::join(|| quick_sort(lo), || quick_sort(lo)); //~ ERROR +} + +fn partition(v: &mut [T]) -> usize { + let pivot = v.len() - 1; + let mut i = 0; + for j in 0..pivot { + if v[j] <= v[pivot] { + v.swap(i, j); + i += 1; + } + } + v.swap(i, pivot); + i +} + +fn main() { } + +``` */ diff --git a/vendor/rayon-core/src/compile_fail/quicksort_race2.rs b/vendor/rayon-core/src/compile_fail/quicksort_race2.rs new file mode 100644 index 0000000000..020589c29a --- /dev/null +++ b/vendor/rayon-core/src/compile_fail/quicksort_race2.rs @@ -0,0 +1,28 @@ +/*! ```compile_fail,E0500 + +fn quick_sort(v: &mut [T]) { + if v.len() <= 1 { + return; + } + + let mid = partition(v); + let (lo, _hi) = v.split_at_mut(mid); + rayon_core::join(|| quick_sort(lo), || quick_sort(v)); //~ ERROR +} + +fn partition(v: &mut [T]) -> usize { + let pivot = v.len() - 1; + let mut i = 0; + for j in 0..pivot { + if v[j] <= v[pivot] { + v.swap(i, j); + i += 1; + } + } + v.swap(i, pivot); + i +} + +fn main() { } + +``` */ diff --git a/vendor/rayon-core/src/compile_fail/quicksort_race3.rs b/vendor/rayon-core/src/compile_fail/quicksort_race3.rs new file mode 100644 index 0000000000..16fbf3b824 --- /dev/null +++ b/vendor/rayon-core/src/compile_fail/quicksort_race3.rs @@ -0,0 +1,28 @@ +/*! ```compile_fail,E0524 + +fn quick_sort(v: &mut [T]) { + if v.len() <= 1 { + return; + } + + let mid = partition(v); + let (_lo, hi) = v.split_at_mut(mid); + rayon_core::join(|| quick_sort(hi), || quick_sort(hi)); //~ ERROR +} + +fn partition(v: &mut [T]) -> usize { + let pivot = v.len() - 1; + let mut i = 0; + for j in 0..pivot { + if v[j] <= v[pivot] { + v.swap(i, j); + i += 1; + } + } + v.swap(i, pivot); + i +} + +fn main() { } + +``` */ diff --git a/vendor/rayon-core/src/compile_fail/rc_return.rs b/vendor/rayon-core/src/compile_fail/rc_return.rs new file mode 100644 index 0000000000..164f8ce5ee --- /dev/null +++ b/vendor/rayon-core/src/compile_fail/rc_return.rs @@ -0,0 +1,21 @@ +/** ```compile_fail,E0277 + +use std::rc::Rc; + +fn main() { + rayon_core::join(|| Rc::new(22), || ()); //~ ERROR +} + +``` */ +mod left {} + +/** ```compile_fail,E0277 + +use std::rc::Rc; + +fn main() { + rayon_core::join(|| (), || Rc::new(23)); //~ ERROR +} + +``` */ +mod right {} diff --git a/vendor/rayon-core/src/compile_fail/rc_upvar.rs b/vendor/rayon-core/src/compile_fail/rc_upvar.rs new file mode 100644 index 0000000000..62895bf22b --- /dev/null +++ b/vendor/rayon-core/src/compile_fail/rc_upvar.rs @@ -0,0 +1,11 @@ +/*! ```compile_fail,E0277 + +use std::rc::Rc; + +fn main() { + let r = Rc::new(22); + rayon_core::join(|| r.clone(), || r.clone()); + //~^ ERROR +} + +``` */ diff --git a/vendor/rayon-core/src/compile_fail/scope_join_bad.rs b/vendor/rayon-core/src/compile_fail/scope_join_bad.rs new file mode 100644 index 0000000000..91eef05798 --- /dev/null +++ b/vendor/rayon-core/src/compile_fail/scope_join_bad.rs @@ -0,0 +1,24 @@ +/*! ```compile_fail,E0597 + +fn bad_scope(f: F) + where F: FnOnce(&i32) + Send, +{ + rayon_core::scope(|s| { + let x = 22; + s.spawn(|_| f(&x)); //~ ERROR `x` does not live long enough + }); +} + +fn good_scope(f: F) + where F: FnOnce(&i32) + Send, +{ + let x = 22; + rayon_core::scope(|s| { + s.spawn(|_| f(&x)); + }); +} + +fn main() { +} + +``` */ diff --git a/vendor/rayon-core/src/join/mod.rs b/vendor/rayon-core/src/join/mod.rs index 28020bc7a0..8233d3bad3 100644 --- a/vendor/rayon-core/src/join/mod.rs +++ b/vendor/rayon-core/src/join/mod.rs @@ -39,7 +39,7 @@ mod test; /// sort for real, you should prefer [the `par_sort` method] offered /// by Rayon). /// -/// [the `par_sort` method]: ../slice/trait.ParallelSliceMut.html#method.par_sort +/// [the `par_sort` method]: ../rayon/slice/trait.ParallelSliceMut.html#method.par_sort /// /// ```rust /// # use rayon_core as rayon; diff --git a/vendor/rayon-core/src/join/test.rs b/vendor/rayon-core/src/join/test.rs index b49a708c10..8955779258 100644 --- a/vendor/rayon-core/src/join/test.rs +++ b/vendor/rayon-core/src/join/test.rs @@ -3,6 +3,7 @@ use ThreadPoolBuilder; use join::*; use rand::{Rng, SeedableRng, XorShiftRng}; +use rand::distributions::Standard; use unwind; fn quick_sort(v: &mut [T]) { @@ -28,10 +29,16 @@ fn partition(v: &mut [T]) -> usize { i } +fn seeded_rng() -> XorShiftRng { + let mut seed = ::Seed::default(); + (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i); + XorShiftRng::from_seed(seed) +} + #[test] fn sort() { - let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); - let mut data: Vec<_> = (0..6 * 1024).map(|_| rng.next_u32()).collect(); + let mut rng = seeded_rng(); + let mut data: Vec = rng.sample_iter(&Standard).take(6 * 1024).collect(); let mut sorted_data = data.clone(); sorted_data.sort(); quick_sort(&mut data); @@ -40,8 +47,8 @@ fn sort() { #[test] fn sort_in_pool() { - let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); - let mut data: Vec<_> = (0..12 * 1024).map(|_| rng.next_u32()).collect(); + let mut rng = seeded_rng(); + let mut data: Vec = rng.sample_iter(&Standard).take(12 * 1024).collect(); let pool = ThreadPoolBuilder::new().build().unwrap(); let mut sorted_data = data.clone(); diff --git a/vendor/rayon-core/src/lib.rs b/vendor/rayon-core/src/lib.rs index 1e85e69f03..b008786b96 100644 --- a/vendor/rayon-core/src/lib.rs +++ b/vendor/rayon-core/src/lib.rs @@ -22,7 +22,6 @@ #![doc(html_root_url = "https://docs.rs/rayon-core/1.4")] #![deny(missing_debug_implementations)] #![deny(missing_docs)] -#![cfg_attr(test, feature(conservative_impl_trait))] use std::any::Any; use std::env; @@ -37,6 +36,8 @@ extern crate crossbeam_deque; extern crate lazy_static; extern crate libc; extern crate num_cpus; + +#[cfg(test)] extern crate rand; #[macro_use] @@ -49,11 +50,13 @@ mod registry; mod scope; mod sleep; mod spawn; -mod test; mod thread_pool; mod unwind; mod util; +mod compile_fail; +mod test; + #[cfg(rayon_unstable)] pub mod internal; pub use thread_pool::ThreadPool; diff --git a/vendor/rayon-core/src/registry.rs b/vendor/rayon-core/src/registry.rs index 18748b3444..0fb8e20385 100644 --- a/vendor/rayon-core/src/registry.rs +++ b/vendor/rayon-core/src/registry.rs @@ -7,14 +7,15 @@ use job::Job; use internal::task::Task; use latch::{LatchProbe, Latch, CountLatch, LockLatch, SpinLatch, TickleLatch}; use log::Event::*; -use rand::{self, Rng}; use sleep::Sleep; use std::any::Any; -use std::cell::{Cell, UnsafeCell}; +use std::cell::Cell; +use std::collections::hash_map::DefaultHasher; +use std::hash::Hasher; use std::sync::{Arc, Mutex, Once, ONCE_INIT}; +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use std::thread; use std::mem; -use std::u32; use std::usize; use unwind; use util::leak; @@ -460,7 +461,7 @@ pub struct WorkerThread { breadth_first: bool, /// A weak random number generator. - rng: UnsafeCell, + rng: XorShift64Star, registry: Arc, } @@ -602,17 +603,8 @@ impl WorkerThread { if num_threads <= 1 { return None; } - assert!(num_threads < (u32::MAX as usize), - "we do not support more than u32::MAX worker threads"); - - let start = { - // OK to use this UnsafeCell because (a) this data is - // confined to current thread, as WorkerThread is not Send - // nor Sync and (b) rand crate will not call back into - // this method. - let rng = &mut *self.rng.get(); - rng.next_u32() % num_threads as u32 - } as usize; + + let start = self.rng.next_usize(num_threads); (start .. num_threads) .chain(0 .. start) .filter(|&i| i != self.index) @@ -646,7 +638,7 @@ unsafe fn main_loop(worker: Deque, worker: worker, breadth_first: breadth_first, index: index, - rng: UnsafeCell::new(rand::weak_rng()), + rng: XorShift64Star::new(), registry: registry.clone(), }; WorkerThread::set_current(&worker_thread); @@ -716,3 +708,43 @@ pub fn in_worker(op: OP) -> R } } } + +/// [xorshift*] is a fast pseudorandom number generator which will +/// even tolerate weak seeding, as long as it's not zero. +/// +/// [xorshift*]: https://en.wikipedia.org/wiki/Xorshift#xorshift* +struct XorShift64Star { + state: Cell, +} + +impl XorShift64Star { + fn new() -> Self { + // Any non-zero seed will do -- this uses the hash of a global counter. + let mut seed = 0; + while seed == 0 { + let mut hasher = DefaultHasher::new(); + static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed)); + seed = hasher.finish(); + } + + XorShift64Star { + state: Cell::new(seed), + } + } + + fn next(&self) -> u64 { + let mut x = self.state.get(); + debug_assert_ne!(x, 0); + x ^= x >> 12; + x ^= x << 25; + x ^= x >> 27; + self.state.set(x); + x.wrapping_mul(0x2545_f491_4f6c_dd1d) + } + + /// Return a value from `0..n`. + fn next_usize(&self, n: usize) -> usize { + (self.next() % n as u64) as usize + } +} diff --git a/vendor/rayon-core/src/scope/test.rs b/vendor/rayon-core/src/scope/test.rs index 088cda5aac..515468fdf6 100644 --- a/vendor/rayon-core/src/scope/test.rs +++ b/vendor/rayon-core/src/scope/test.rs @@ -5,6 +5,7 @@ use std::cmp; use std::iter::once; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Mutex; +use std::vec; use unwind; #[test] @@ -74,7 +75,7 @@ struct Tree { } impl Tree { - pub fn iter<'s>(&'s self) -> impl Iterator + 's { + pub fn iter<'s>(&'s self) -> vec::IntoIter<&'s T> { once(&self.value) .chain(self.children.iter().flat_map(|c| c.iter())) .collect::>() // seems like it shouldn't be needed... but prevents overflow @@ -104,7 +105,9 @@ impl Tree { fn random_tree(depth: usize) -> Tree { assert!(depth > 0); - let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); + let mut seed = ::Seed::default(); + (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i); + let mut rng = XorShiftRng::from_seed(seed); random_tree1(depth, &mut rng) } @@ -112,13 +115,13 @@ fn random_tree1(depth: usize, rng: &mut XorShiftRng) -> Tree { let children = if depth == 0 { vec![] } else { - (0..(rng.next_u32() % 3)) // somewhere between 0 and 3 children at each level + (0..rng.gen_range(0, 4)) // somewhere between 0 and 3 children at each level .map(|_| random_tree1(depth - 1, rng)) .collect() }; Tree { - value: rng.next_u32() % 1_000_000, + value: rng.gen_range(0, 1_000_000), children: children, } } diff --git a/vendor/rayon-core/tests/double_init_fail.rs b/vendor/rayon-core/tests/double_init_fail.rs new file mode 100644 index 0000000000..2b9818465e --- /dev/null +++ b/vendor/rayon-core/tests/double_init_fail.rs @@ -0,0 +1,12 @@ +extern crate rayon_core; + +use rayon_core::ThreadPoolBuilder; +use std::error::Error; + +#[test] +fn double_init_fail() { + let result1 = ThreadPoolBuilder::new().build_global(); + assert_eq!(result1.unwrap(), ()); + let err = ThreadPoolBuilder::new().build_global().unwrap_err(); + assert!(err.description() == "The global thread pool has already been initialized."); +} diff --git a/vendor/rayon-core/tests/init_zero_threads.rs b/vendor/rayon-core/tests/init_zero_threads.rs new file mode 100644 index 0000000000..eb4137e9a7 --- /dev/null +++ b/vendor/rayon-core/tests/init_zero_threads.rs @@ -0,0 +1,11 @@ +extern crate rayon_core; + +use rayon_core::ThreadPoolBuilder; + +#[test] +fn init_zero_threads() { + ThreadPoolBuilder::new() + .num_threads(0) + .build_global() + .unwrap(); +} diff --git a/vendor/rayon-core/tests/scope_join.rs b/vendor/rayon-core/tests/scope_join.rs new file mode 100644 index 0000000000..30985eb74f --- /dev/null +++ b/vendor/rayon-core/tests/scope_join.rs @@ -0,0 +1,47 @@ +extern crate rayon_core; + +/// Test that one can emulate join with `scope`: +fn pseudo_join(f: F, g: G) +where + F: FnOnce() + Send, + G: FnOnce() + Send, +{ + rayon_core::scope(|s| { + s.spawn(|_| g()); + f(); + }); +} + +fn quick_sort(v: &mut [T]) { + if v.len() <= 1 { + return; + } + + let mid = partition(v); + let (lo, hi) = v.split_at_mut(mid); + pseudo_join(|| quick_sort(lo), || quick_sort(hi)); +} + +fn partition(v: &mut [T]) -> usize { + let pivot = v.len() - 1; + let mut i = 0; + for j in 0..pivot { + if v[j] <= v[pivot] { + v.swap(i, j); + i += 1; + } + } + v.swap(i, pivot); + i +} + +fn is_sorted(v: &[T]) -> bool { + (1..v.len()).all(|i| v[i - 1] <= v[i]) +} + +#[test] +fn scope_join() { + let mut v: Vec = (0..256).rev().collect(); + quick_sort(&mut v); + assert!(is_sorted(&v)); +} diff --git a/vendor/rayon-core/tests/simple_panic.rs b/vendor/rayon-core/tests/simple_panic.rs new file mode 100644 index 0000000000..3a5a7890a7 --- /dev/null +++ b/vendor/rayon-core/tests/simple_panic.rs @@ -0,0 +1,9 @@ +extern crate rayon_core; + +use rayon_core::join; + +#[test] +#[should_panic(expected = "should panic")] +fn simple_panic() { + join(|| {}, || panic!("should panic")); +} diff --git a/vendor/rayon-core/tests/stack_overflow_crash.rs b/vendor/rayon-core/tests/stack_overflow_crash.rs new file mode 100644 index 0000000000..ba0d5b1d23 --- /dev/null +++ b/vendor/rayon-core/tests/stack_overflow_crash.rs @@ -0,0 +1,59 @@ +extern crate rayon_core; + +use rayon_core::ThreadPoolBuilder; + +use std::process::Command; +use std::env; + +#[cfg(target_os = "linux")] +use std::os::unix::process::ExitStatusExt; + +fn force_stack_overflow(depth: u32) { + let _buffer = [0u8; 1024 * 1024]; + if depth > 0 { + force_stack_overflow(depth - 1); + } +} + +fn main() { + if env::args().len() == 1 { + // first check that the recursivecall actually causes a stack overflow, and does not get optimized away + { + let status = Command::new(env::current_exe().unwrap()) + .arg("8") + .status() + .unwrap(); + + #[cfg(windows)] + assert_eq!(status.code(), Some(0xc00000fd /*STATUS_STACK_OVERFLOW*/)); + + #[cfg(unix)] + assert_eq!(status.code(), None); + + #[cfg(target_os = "linux")] + assert!( + status.signal() == Some(11 /*SIGABRT*/) || status.signal() == Some(6 /*SIGSEGV*/) + ); + } + + // now run with a larger stack and verify correct operation + { + let status = Command::new(env::current_exe().unwrap()) + .arg("48") + .status() + .unwrap(); + assert_eq!(status.code(), Some(0)); + #[cfg(target_os = "linux")] + assert_eq!(status.signal(), None); + } + } else { + let stack_size_in_mb: usize = env::args().nth(1).unwrap().parse().unwrap(); + let pool = ThreadPoolBuilder::new() + .stack_size(stack_size_in_mb * 1024 * 1024) + .build() + .unwrap(); + pool.install(|| { + force_stack_overflow(32); + }); + } +} diff --git a/vendor/rdrand/.cargo-checksum.json b/vendor/rdrand/.cargo-checksum.json new file mode 100644 index 0000000000..c7b5a11ac8 --- /dev/null +++ b/vendor/rdrand/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"f11ed31fc1b481c7d0e24251d7d60d34442f1d25747c887c49dc9fbad7e13e59","LICENSE":"00d7b0c8bf95ea93162fccc84da96b906b15add708eade04f7ee6141f7b53141","README.mkd":"93853e9e773543ed0d0cf696b5fb151b15bddc1ad9c39996c9eb11b20a3c7ff6","appveyor.yml":"f502d8a0755b98e904a40b07e8ba270bccd729045b03c24a7db0dfbb4047b515","benches/rdrand.rs":"f3684c360d43bc8a780868c0a3af43b20d56975e03575122cee87277787cc8d0","benches/rdseed.rs":"520097b15a3f11c0c6a357e6cd23add598be22f37839bbc71040b827b05d1064","benches/std.rs":"6a5b52b070b2a594e735aa617f16fc6a861e64534634cdb61801c3297444f6fe","src/changelog.rs":"644e08c06836ecdf94f9a43aec109e9f05f9d85f00541683c72d0d3893ff8d6a","src/lib.rs":"8fc306db8a304d24c28fcefaec1849c0d8bbca97417420af7b81449c352b2e92"},"package":"678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"} \ No newline at end of file diff --git a/vendor/rdrand/Cargo.toml b/vendor/rdrand/Cargo.toml new file mode 100644 index 0000000000..6b3c80a872 --- /dev/null +++ b/vendor/rdrand/Cargo.toml @@ -0,0 +1,28 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "rdrand" +version = "0.4.0" +authors = ["Simonas Kazlauskas "] +description = "An implementation of random number generator based on rdrand and rdseed instructions" +documentation = "https://docs.rs/rdrand/0.4.0/" +keywords = ["rand", "rdrand", "rdseed", "random"] +license = "ISC" +repository = "https://github.com/nagisa/rust_rdrand/" +[dependencies.rand_core] +version = "0.3" +default-features = false + +[features] +default = ["std"] +std = [] diff --git a/vendor/rdrand/LICENSE b/vendor/rdrand/LICENSE new file mode 100644 index 0000000000..4d6f40d43b --- /dev/null +++ b/vendor/rdrand/LICENSE @@ -0,0 +1,12 @@ +Copyright © 2014, Simonas Kazlauskas + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without +fee is hereby granted, provided that the above copyright notice and this permission notice appear +in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/vendor/rdrand/README.mkd b/vendor/rdrand/README.mkd new file mode 100644 index 0000000000..55ab48b8e9 --- /dev/null +++ b/vendor/rdrand/README.mkd @@ -0,0 +1,8 @@ +An implementation of random number generators based on `rdrand` and `rdseed` instructions. + +The random number generators provided by this crate are fairly slow (the latency for these +instructions is pretty high), but provide high quality random bits. Caveat is: neither AMD’s +nor Intel’s designs are public and therefore are not verifiable for lack of backdoors. + +Unless you know what you are doing, use the random number generators provided by the `rand` +crate (such as `EntropyRng`) instead. diff --git a/vendor/rdrand/appveyor.yml b/vendor/rdrand/appveyor.yml new file mode 100644 index 0000000000..2e915cf4f9 --- /dev/null +++ b/vendor/rdrand/appveyor.yml @@ -0,0 +1,27 @@ +environment: + matrix: + - TARGET: 1.30.0-x86_64-pc-windows-msvc + - TARGET: 1.30.0-i686-pc-windows-msvc + - TARGET: 1.30.0-x86_64-pc-windows-gnu + - TARGET: 1.30.0-i686-pc-windows-gnu + - TARGET: nightly-x86_64-pc-windows-msvc + - TARGET: nightly-i686-pc-windows-msvc +install: + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust.exe" + - ps: .\rust.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null + - ps: $env:PATH="$env:PATH;C:\rust\bin" + - rustc -vV + - cargo -vV +build: off + +test_script: +- cargo test +- cargo test --no-default-features + +for: +- matrix: + only: + - TARGET: nightly-x86_64-pc-windows-msvc + - TARGET: nightly-i686-pc-windows-msvc + test_script: + - cargo bench diff --git a/vendor/rdrand/benches/rdrand.rs b/vendor/rdrand/benches/rdrand.rs new file mode 100644 index 0000000000..7e70c233e5 --- /dev/null +++ b/vendor/rdrand/benches/rdrand.rs @@ -0,0 +1,49 @@ +#![feature(test)] +extern crate rand_core; +extern crate rdrand; +extern crate test; + +use rand_core::RngCore; +use test::Bencher; + +#[bench] +fn bench_u16(b : &mut Bencher) { + if let Ok(gen) = rdrand::RdRand::new() { + b.bytes = 2; + b.iter(|| { + gen.try_next_u16().unwrap() + }); + } +} + +#[bench] +fn bench_u32(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdRand::new() { + b.bytes = 4; + b.iter(|| { + gen.next_u32() + }); + } +} + +#[bench] +fn bench_u64(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdRand::new() { + b.bytes = 8; + b.iter(|| { + gen.next_u64() + }); + } +} + +#[bench] +fn bench_fill(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdRand::new() { + let mut buffer = [0; 128]; + b.bytes = 128; + b.iter(|| { + gen.fill_bytes(&mut buffer); + buffer + }); + } +} diff --git a/vendor/rdrand/benches/rdseed.rs b/vendor/rdrand/benches/rdseed.rs new file mode 100644 index 0000000000..6bf8cebf9b --- /dev/null +++ b/vendor/rdrand/benches/rdseed.rs @@ -0,0 +1,49 @@ +#![feature(test)] +extern crate rand_core; +extern crate rdrand; +extern crate test; + +use rand_core::RngCore; +use test::Bencher; + +#[bench] +fn bench_rdseed_u16(b : &mut Bencher) { + if let Ok(gen) = rdrand::RdSeed::new() { + b.bytes = 2; + b.iter(|| { + gen.try_next_u16().unwrap() + }); + } +} + +#[bench] +fn bench_rdseed_u32(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdSeed::new() { + b.bytes = 4; + b.iter(|| { + gen.next_u32() + }); + } +} + +#[bench] +fn bench_rdseed_u64(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdSeed::new() { + b.bytes = 8; + b.iter(|| { + gen.next_u64() + }); + } +} + +#[bench] +fn bench_fill(b : &mut Bencher) { + if let Ok(mut gen) = rdrand::RdSeed::new() { + let mut buffer = [0; 128]; + b.bytes = 128; + b.iter(|| { + gen.fill_bytes(&mut buffer); + buffer + }); + } +} diff --git a/vendor/rdrand/benches/std.rs b/vendor/rdrand/benches/std.rs new file mode 100644 index 0000000000..3fa8fadd95 --- /dev/null +++ b/vendor/rdrand/benches/std.rs @@ -0,0 +1,31 @@ +// #![feature(test)] +// extern crate rand; +// extern crate test; +// +// use test::Bencher; +// use test::black_box; +// use rand::Rng; +// use rand::StdRng; +// use rand::OsRng; +// +// // OsRng is supposed to be the default for crypto uses. +// #[bench] +// fn bench_osrng_u64(b : &mut Bencher) { +// if let Ok(mut gen) = OsRng::new() { +// b.bytes = 8; +// b.iter(|| { +// black_box(gen.next_u64()); +// }); +// } +// } +// +// // StdRng is the default for everything else. +// #[bench] +// fn bench_stdrng_u64(b : &mut Bencher) { +// if let Ok(mut gen) = StdRng::new() { +// b.bytes = 8; +// b.iter(|| { +// gen.next_u64(); +// }); +// } +// } diff --git a/vendor/rdrand/src/changelog.rs b/vendor/rdrand/src/changelog.rs new file mode 100644 index 0000000000..503f738106 --- /dev/null +++ b/vendor/rdrand/src/changelog.rs @@ -0,0 +1,25 @@ +//! Project changelog + +/// ## Breaking changes +/// +/// Crate gained an enabled-by-default `std` feature. If you relied on rdrand being `core`-able +/// change your dependency to appear as such: +/// +/// ```toml +/// rdrand = { version = "0.4", default-features = false } +/// ``` +/// +/// This is done so that an advantage of the common feature detection functionality could be +/// employed by users that are not constrained by `core`. This functionality is faster, caches the +/// results and is shared between all users of the functionality. +/// +/// For `core` usage the feature detection has also been improved and will not be done if e.g. +/// crate is built with `rdrand` instructions enabled globally. +pub mod r0_4_0 {} + +/// Crate now works on stable! +/// +/// ## Breaking changes +/// +/// * Updated to `rand_core = ^0.3`. +pub mod r0_3_0 {} diff --git a/vendor/rdrand/src/lib.rs b/vendor/rdrand/src/lib.rs new file mode 100644 index 0000000000..423ae2139b --- /dev/null +++ b/vendor/rdrand/src/lib.rs @@ -0,0 +1,472 @@ +// Copyright © 2014, Simonas Kazlauskas +// +// Permission to use, copy, modify, and/or distribute this software for any purpose with or without +// fee is hereby granted, provided that the above copyright notice and this permission notice +// appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +// OF THIS SOFTWARE. +//! An implementation of random number generators based on `rdrand` and `rdseed` instructions. +//! +//! The random number generators provided by this crate are fairly slow (the latency for these +//! instructions is pretty high), but provide high quality random bits. Caveat is: neither AMD’s +//! nor Intel’s designs are public and therefore are not verifiable for lack of backdoors. +//! +//! Unless you know what you are doing, use the random number generators provided by the `rand` +//! crate (such as `OsRng`) instead. +//! +//! Here are a measurements for select processor architectures. Check [Agner’s instruction tables] +//! for up-to-date listings. +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//!
ArchitectureLatency (cycles)Maximum throughput (per core)
u16u32u64
AMD Ryzen~1200~1200~2500~12MB/s @ 3.7GHz
Intel Skylake460460460~72MB/s @ 4.2GHz
Intel Haswell320320320~110MB/s @ 4.4GHz
+//! +//! [Agner’s instruction tables]: http://agner.org/optimize/ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate rand_core; + +#[cfg(feature = "std")] +extern crate core; + +pub mod changelog; + +use rand_core::{RngCore, CryptoRng, Error, ErrorKind}; +use core::slice; + +const RETRY_LIMIT: u8 = 127; + +#[cold] +#[inline(never)] +pub(crate) fn busy_loop_fail() -> ! { + panic!("hardware generator failure"); +} + +/// A cryptographically secure statistically uniform, non-periodic and non-deterministic random bit +/// generator. +/// +/// Note that this generator may be implemented using a deterministic algorithm that is reseeded +/// routinely from a non-deterministic entropy source to achieve the desirable properties. +/// +/// This generator is a viable replacement to any generator, however, since nobody has audited +/// Intel or AMD hardware yet, the usual disclaimers as to their suitability apply. +/// +/// It is potentially faster than `OsRng`, but is only supported on more recent Intel (Ivy Bridge +/// and later) and AMD (Ryzen and later) processors. +#[derive(Clone, Copy)] +pub struct RdRand(()); + +/// A cryptographically secure non-deterministic random bit generator. +/// +/// This generator produces high-entropy output and is suited to seed other pseudo-random +/// generators. +/// +/// This instruction currently is only available in Intel Broadwell (and later) and AMD Ryzen +/// processors. +/// +/// This generator is not intended for general random number generation purposes and should be used +/// to seed other generators implementing [rand_core::SeedableRng]. +#[derive(Clone, Copy)] +pub struct RdSeed(()); + +impl CryptoRng for RdRand {} +impl CryptoRng for RdSeed {} + +mod arch { + #[cfg(target_arch = "x86_64")] + pub use core::arch::x86_64::*; + #[cfg(target_arch = "x86")] + pub use core::arch::x86::*; + + #[cfg(target_arch = "x86")] + pub(crate) unsafe fn _rdrand64_step(dest: &mut u64) -> i32 { + let mut ret1: u32 = ::core::mem::uninitialized(); + let mut ret2: u32 = ::core::mem::uninitialized(); + if _rdrand32_step(&mut ret1) != 0 && _rdrand32_step(&mut ret2) != 0 { + *dest = (ret1 as u64) << 32 | (ret2 as u64); + 1 + } else { + 0 + } + } + + #[cfg(target_arch = "x86")] + pub(crate) unsafe fn _rdseed64_step(dest: &mut u64) -> i32 { + let mut ret1: u32 = ::core::mem::uninitialized(); + let mut ret2: u32 = ::core::mem::uninitialized(); + if _rdseed32_step(&mut ret1) != 0 && _rdseed32_step(&mut ret2) != 0 { + *dest = (ret1 as u64) << 32 | (ret2 as u64); + 1 + } else { + 0 + } + } +} + +#[cfg(not(feature = "std"))] +macro_rules! is_x86_feature_detected { + ("rdrand") => {{ + if cfg!(target_feature="rdrand") { + true + } else if cfg!(target_env = "sgx") { + false + } else { + const FLAG : u32 = 1 << 30; + unsafe { ::arch::__cpuid(1).ecx & FLAG == FLAG } + } + }}; + ("rdseed") => {{ + if cfg!(target_feature = "rdseed") { + true + } else if cfg!(target_env = "sgx") { + false + } else { + const FLAG : u32 = 1 << 18; + unsafe { ::arch::__cpuid(7).ebx & FLAG == FLAG } + } + }}; +} + +macro_rules! loop_rand { + ($el: ty, $step: path) => { { + let mut idx = 0; + loop { + let mut el: $el = ::core::mem::uninitialized(); + if $step(&mut el) != 0 { + break Some(el); + } else if idx == RETRY_LIMIT { + break None; + } + idx += 1; + } + } } +} + +macro_rules! impl_rand { + ($gen:ident, $feat:tt, $step16: path, $step32:path, $step64:path, + maxstep = $maxstep:path, maxty = $maxty: ty) => { + impl $gen { + /// Create a new instance of the random number generator. + /// + /// This constructor checks whether the CPU the program is running on supports the + /// instruction necessary for this generator to operate. If the instruction is not + /// supported, an error is returned. + pub fn new() -> Result { + if is_x86_feature_detected!($feat) { + Ok($gen(())) + } else { + Err(Error::new(rand_core::ErrorKind::Unavailable, + "the instruction is not supported")) + } + } + + /// Generate a single random `u16` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return `None`. + /// + /// In case `None` is returned, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + pub fn try_next_u16(&self) -> Option { + #[target_feature(enable = $feat)] + unsafe fn imp() + -> Option { + loop_rand!(u16, $step16) + } + unsafe { imp() } + } + + /// Generate a single random `u32` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return `None`. + /// + /// In case `None` is returned, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + pub fn try_next_u32(&self) -> Option { + #[target_feature(enable = $feat)] + unsafe fn imp() + -> Option { + loop_rand!(u32, $step32) + } + unsafe { imp() } + } + + /// Generate a single random `u64` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return `None`. + /// + /// In case `None` is returned, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + /// + /// Note, that on 32-bit targets, there’s no underlying instruction to generate a + /// 64-bit number, so it is emulated with the 32-bit version of the instruction. + #[inline(always)] + pub fn try_next_u64(&self) -> Option { + #[target_feature(enable = $feat)] + unsafe fn imp() + -> Option { + loop_rand!(u64, $step64) + } + unsafe { imp() } + } + } + + impl RngCore for $gen { + /// Generate a single random `u32` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// # Panic + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will `panic`. + /// + /// In case `panic` occurs, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + fn next_u32(&mut self) -> u32 { + if let Some(result) = self.try_next_u32() { + result + } else { + busy_loop_fail() + } + } + + /// Generate a single random `u64` value. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// Note, that on 32-bit targets, there’s no underlying instruction to generate a + /// 64-bit number, so it is emulated with the 32-bit version of the instruction. + /// + /// # Panic + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will `panic`. + /// + /// In case `panic` occurs, the caller should assume that an non-recoverable + /// hardware failure has occured and use another random number genrator instead. + #[inline(always)] + fn next_u64(&mut self) -> u64 { + if let Some(result) = self.try_next_u64() { + result + } else { + busy_loop_fail() + } + } + + /// Fill a buffer `dest` with random data. + /// + /// See `try_fill_bytes` for a more extensive documentation. + /// + /// # Panic + /// + /// This method will panic any time `try_fill_bytes` would return an error. + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + if let Err(_) = self.try_fill_bytes(dest) { + busy_loop_fail() + } + } + + /// Fill a buffer `dest` with random data. + /// + /// This method will use the most appropriate variant of the instruction available on + /// the machine to achieve the greatest single-core throughput, however it has a + /// slightly higher setup cost than the plain `next_u32` or `next_u64` methods. + /// + /// The underlying instruction may fail for variety reasons (such as actual hardware + /// failure or exhausted entropy), however the exact reason for the failure is not + /// usually exposed. + /// + /// This method will retry calling the instruction a few times, however if all the + /// attempts fail, it will return an error. + /// + /// If an error is returned, the caller should assume that an non-recoverable hardware + /// failure has occured and use another random number genrator instead. + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) + -> Result<(), Error> { + #[target_feature(enable = $feat)] + unsafe fn imp(dest: &mut [u8]) + -> Result<(), Error> + { + unsafe fn imp_less_fast(mut dest: &mut [u8], word: &mut $maxty, + buffer: &mut &[u8]) + -> Result<(), Error> + { + while !dest.is_empty() { + if buffer.is_empty() { + if let Some(w) = loop_rand!($maxty, $maxstep) { + *word = w; + *buffer = slice::from_raw_parts( + word as *const _ as *const u8, + ::core::mem::size_of::<$maxty>() + ); + } else { + return Err(Error::new(ErrorKind::Unexpected, + "hardware generator failure")); + } + } + + let len = dest.len().min(buffer.len()); + let (copy_src, leftover) = buffer.split_at(len); + let (copy_dest, dest_leftover) = { dest }.split_at_mut(len); + *buffer = leftover; + dest = dest_leftover; + ::core::ptr::copy_nonoverlapping( + copy_src.as_ptr(), copy_dest.as_mut_ptr(), len + ); + } + Ok(()) + } + + let destlen = dest.len(); + if destlen > ::core::mem::size_of::<$maxty>() { + let (left, mid, right) = dest.align_to_mut(); + let mut word = 0; + let mut buffer: &[u8] = &[]; + + for el in mid { + if let Some(val) = loop_rand!($maxty, $maxstep) { + *el = val; + } else { + return Err(Error::new(ErrorKind::Unexpected, + "hardware generator failure")); + } + } + + imp_less_fast(left, &mut word, &mut buffer)?; + imp_less_fast(right, &mut word, &mut buffer) + } else { + let mut word = 0; + let mut buffer: &[u8] = &[]; + imp_less_fast(dest, &mut word, &mut buffer) + } + } + unsafe { imp(dest) } + } + } + } +} + +#[cfg(target_arch = "x86_64")] +impl_rand!(RdRand, "rdrand", + ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step, + maxstep = ::arch::_rdrand64_step, maxty = u64); +#[cfg(target_arch = "x86_64")] +impl_rand!(RdSeed, "rdseed", + ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step, + maxstep = ::arch::_rdseed64_step, maxty = u64); +#[cfg(target_arch = "x86")] +impl_rand!(RdRand, "rdrand", + ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step, + maxstep = ::arch::_rdrand32_step, maxty = u32); +#[cfg(target_arch = "x86")] +impl_rand!(RdSeed, "rdseed", + ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step, + maxstep = ::arch::_rdseed32_step, maxty = u32); + +#[test] +fn rdrand_works() { + let _ = RdRand::new().map(|mut r| { + r.next_u32(); + r.next_u64(); + }); +} + +#[test] +fn fill_fills_all_bytes() { + let _ = RdRand::new().map(|mut r| { + let mut peach; + let mut banana; + let mut start = 0; + let mut end = 128; + 'outer: while start < end { + banana = [0; 128]; + for _ in 0..512 { + peach = [0; 128]; + r.fill_bytes(&mut peach[start..end]); + for (b, p) in banana.iter_mut().zip(peach.iter()) { + *b = *b | *p; + } + if (&banana[start..end]).iter().all(|x| *x != 0) { + assert!(banana[..start].iter().all(|x| *x == 0), "all other values must be 0"); + assert!(banana[end..].iter().all(|x| *x == 0), "all other values must be 0"); + if start < 17 { + start += 1; + } else { + end -= 3; + } + continue 'outer; + } + } + panic!("wow, we broke it? {} {} {:?}", start, end, &banana[..]) + } + }); +} + +#[test] +fn rdseed_works() { + let _ = RdSeed::new().map(|mut r| { + r.next_u32(); + r.next_u64(); + }); +} diff --git a/vendor/rustc-demangle/.cargo-checksum.json b/vendor/rustc-demangle/.cargo-checksum.json index 9e0bf5e14d..d87dcb5805 100644 --- a/vendor/rustc-demangle/.cargo-checksum.json +++ b/vendor/rustc-demangle/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"5946ab741498cc88056a98357ea698ce2ab1ea6fc2098980f914c5546df87db3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"7bb7dbc6378a31b5b925a0cff628a69006c77a4cdf3533f7507b7c8fbe3492b0","src/lib.rs":"b1fbe3850a7b81c79ef161543897a9c47b79715e6ac95c54799c4cc3b60abf45"},"package":"82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"} \ No newline at end of file +{"files":{"Cargo.toml":"1053f5e93d51d05f1863bdc806494a3439b4c5e44bb601c8b7b5c7af9ae88f9e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"7bb7dbc6378a31b5b925a0cff628a69006c77a4cdf3533f7507b7c8fbe3492b0","src/legacy.rs":"6ee0396373647f2f555d2226da667a8d222324e517b2c7b0a0367c171754bcdf","src/lib.rs":"53d01da4bdb1965e73e9b5d6613aa51abc8dc6dde86bfdcc59e6ddcf11e210fa","src/v0.rs":"740fa3ed15cee542e38e939226fb25e8c3034561899085e0c97cf8bd1743037e"},"package":"a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"} \ No newline at end of file diff --git a/vendor/rustc-demangle/Cargo.toml b/vendor/rustc-demangle/Cargo.toml index a47ef828e5..07935ed465 100644 --- a/vendor/rustc-demangle/Cargo.toml +++ b/vendor/rustc-demangle/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "rustc-demangle" -version = "0.1.10" +version = "0.1.15" authors = ["Alex Crichton "] description = "Rust compiler symbol demangling.\n" homepage = "https://github.com/alexcrichton/rustc-demangle" diff --git a/vendor/rustc-demangle/src/legacy.rs b/vendor/rustc-demangle/src/legacy.rs new file mode 100644 index 0000000000..1e1824c6ce --- /dev/null +++ b/vendor/rustc-demangle/src/legacy.rs @@ -0,0 +1,370 @@ +use core::fmt; + +/// Representation of a demangled symbol name. +pub struct Demangle<'a> { + inner: &'a str, + /// The number of ::-separated elements in the original name. + elements: usize, +} + +/// De-mangles a Rust symbol into a more readable version +/// +/// All Rust symbols by default are mangled as they contain characters that +/// cannot be represented in all object files. The mangling mechanism is similar +/// to C++'s, but Rust has a few specifics to handle items like lifetimes in +/// symbols. +/// +/// This function will take a **mangled** symbol and return a value. When printed, +/// the de-mangled version will be written. If the symbol does not look like +/// a mangled symbol, the original value will be written instead. +/// +/// # Examples +/// +/// ``` +/// use rustc_demangle::demangle; +/// +/// assert_eq!(demangle("_ZN4testE").to_string(), "test"); +/// assert_eq!(demangle("_ZN3foo3barE").to_string(), "foo::bar"); +/// assert_eq!(demangle("foo").to_string(), "foo"); +/// ``` + +// All Rust symbols are in theory lists of "::"-separated identifiers. Some +// assemblers, however, can't handle these characters in symbol names. To get +// around this, we use C++-style mangling. The mangling method is: +// +// 1. Prefix the symbol with "_ZN" +// 2. For each element of the path, emit the length plus the element +// 3. End the path with "E" +// +// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar". +// +// We're the ones printing our backtraces, so we can't rely on anything else to +// demangle our symbols. It's *much* nicer to look at demangled symbols, so +// this function is implemented to give us nice pretty output. +// +// Note that this demangler isn't quite as fancy as it could be. We have lots +// of other information in our symbols like hashes, version, type information, +// etc. Additionally, this doesn't handle glue symbols at all. +pub fn demangle(s: &str) -> Result { + // First validate the symbol. If it doesn't look like anything we're + // expecting, we just print it literally. Note that we must handle non-Rust + // symbols because we could have any function in the backtrace. + let inner; + if s.len() > 4 && s.starts_with("_ZN") && s.ends_with('E') { + inner = &s[3..s.len() - 1]; + } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with('E') { + // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" + // form too. + inner = &s[2..s.len() - 1]; + } else if s.len() > 5 && s.starts_with("__ZN") && s.ends_with('E') { + // On OSX, symbols are prefixed with an extra _ + inner = &s[4..s.len() - 1]; + } else { + return Err(()); + } + + // only work with ascii text + if inner.bytes().any(|c| c & 0x80 != 0) { + return Err(()); + } + + let mut elements = 0; + let mut chars = inner.chars().peekable(); + loop { + let mut i = 0usize; + while let Some(&c) = chars.peek() { + if !c.is_digit(10) { + break + } + chars.next(); + let next = i.checked_mul(10) + .and_then(|i| i.checked_add(c as usize - '0' as usize)); + i = match next { + Some(i) => i, + None => { + return Err(()); + } + }; + } + + if i == 0 { + if !chars.next().is_none() { + return Err(()); + } + break; + } else if chars.by_ref().take(i).count() != i { + return Err(()); + } else { + elements += 1; + } + } + + Ok(Demangle { + inner: inner, + elements: elements, + }) +} + +// Rust hashes are hex digits with an `h` prepended. +fn is_rust_hash(s: &str) -> bool { + s.starts_with('h') && s[1..].chars().all(|c| c.is_digit(16)) +} + +impl<'a> fmt::Display for Demangle<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Alright, let's do this. + let mut inner = self.inner; + for element in 0..self.elements { + let mut rest = inner; + while rest.chars().next().unwrap().is_digit(10) { + rest = &rest[1..]; + } + let i: usize = inner[..(inner.len() - rest.len())].parse().unwrap(); + inner = &rest[i..]; + rest = &rest[..i]; + // Skip printing the hash if alternate formatting + // was requested. + if f.alternate() && element+1 == self.elements && is_rust_hash(&rest) { + break; + } + if element != 0 { + try!(f.write_str("::")); + } + if rest.starts_with("_$") { + rest = &rest[1..]; + } + while !rest.is_empty() { + if rest.starts_with('.') { + if let Some('.') = rest[1..].chars().next() { + try!(f.write_str("::")); + rest = &rest[2..]; + } else { + try!(f.write_str(".")); + rest = &rest[1..]; + } + } else if rest.starts_with('$') { + macro_rules! demangle { + ($($pat:expr => $demangled:expr,)*) => ({ + $(if rest.starts_with($pat) { + try!(f.write_str($demangled)); + rest = &rest[$pat.len()..]; + } else)* + { + try!(f.write_str(rest)); + break; + } + + }) + } + + // see src/librustc/back/link.rs for these mappings + demangle! { + "$SP$" => "@", + "$BP$" => "*", + "$RF$" => "&", + "$LT$" => "<", + "$GT$" => ">", + "$LP$" => "(", + "$RP$" => ")", + "$C$" => ",", + + // in theory we can demangle any Unicode code point, but + // for simplicity we just catch the common ones. + "$u7e$" => "~", + "$u20$" => " ", + "$u27$" => "'", + "$u3d$" => "=", + "$u5b$" => "[", + "$u5d$" => "]", + "$u7b$" => "{", + "$u7d$" => "}", + "$u3b$" => ";", + "$u2b$" => "+", + "$u21$" => "!", + "$u22$" => "\"", + } + } else { + let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') { + None => rest.len(), + Some((i, _)) => i, + }; + try!(f.write_str(&rest[..idx])); + rest = &rest[idx..]; + } + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::prelude::v1::*; + + macro_rules! t { + ($a:expr, $b:expr) => (assert!(ok($a, $b))) + } + + macro_rules! t_err { + ($a:expr) => (assert!(ok_err($a))) + } + + macro_rules! t_nohash { + ($a:expr, $b:expr) => ({ + assert_eq!(format!("{:#}", ::demangle($a)), $b); + }) + } + + fn ok(sym: &str, expected: &str) -> bool { + match ::try_demangle(sym) { + Ok(s) => { + if s.to_string() == expected { + true + } else { + println!("\n{}\n!=\n{}\n", s, expected); + false + } + } + Err(_) => { + println!("error demangling"); + false + } + } + } + + fn ok_err(sym: &str) -> bool { + match ::try_demangle(sym) { + Ok(_) => { + println!("succeeded in demangling"); + false + } + Err(_) => ::demangle(sym).to_string() == sym, + } + } + + #[test] + fn demangle() { + t_err!("test"); + t!("_ZN4testE", "test"); + t_err!("_ZN4test"); + t!("_ZN4test1a2bcE", "test::a::bc"); + } + + #[test] + fn demangle_dollars() { + t!("_ZN4$RP$E", ")"); + t!("_ZN8$RF$testE", "&test"); + t!("_ZN8$BP$test4foobE", "*test::foob"); + t!("_ZN9$u20$test4foobE", " test::foob"); + t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>"); + } + + #[test] + fn demangle_many_dollars() { + t!("_ZN13test$u20$test4foobE", "test test::foob"); + t!("_ZN12test$BP$test4foobE", "test*test::foob"); + } + + + #[test] + fn demangle_osx() { + t!("__ZN5alloc9allocator6Layout9for_value17h02a996811f781011E", "alloc::allocator::Layout::for_value::h02a996811f781011"); + t!("__ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap18_MSG_FILE_LINE_COL17haf7cb8d5824ee659E", ">::unwrap::_MSG_FILE_LINE_COL::haf7cb8d5824ee659"); + t!("__ZN4core5slice89_$LT$impl$u20$core..iter..traits..IntoIterator$u20$for$u20$$RF$$u27$a$u20$$u5b$T$u5d$$GT$9into_iter17h450e234d27262170E", "core::slice::::into_iter::h450e234d27262170"); + } + + #[test] + fn demangle_windows() { + t!("ZN4testE", "test"); + t!("ZN13test$u20$test4foobE", "test test::foob"); + t!("ZN12test$RF$test4foobE", "test&test::foob"); + } + + #[test] + fn demangle_elements_beginning_with_underscore() { + t!("_ZN13_$LT$test$GT$E", ""); + t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}"); + t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR"); + } + + #[test] + fn demangle_trait_impls() { + t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE", + ">::bar"); + } + + #[test] + fn demangle_without_hash() { + let s = "_ZN3foo17h05af221e174051e9E"; + t!(s, "foo::h05af221e174051e9"); + t_nohash!(s, "foo"); + } + + #[test] + fn demangle_without_hash_edgecases() { + // One element, no hash. + t_nohash!("_ZN3fooE", "foo"); + // Two elements, no hash. + t_nohash!("_ZN3foo3barE", "foo::bar"); + // Longer-than-normal hash. + t_nohash!("_ZN3foo20h05af221e174051e9abcE", "foo"); + // Shorter-than-normal hash. + t_nohash!("_ZN3foo5h05afE", "foo"); + // Valid hash, but not at the end. + t_nohash!("_ZN17h05af221e174051e93fooE", "h05af221e174051e9::foo"); + // Not a valid hash, missing the 'h'. + t_nohash!("_ZN3foo16ffaf221e174051e9E", "foo::ffaf221e174051e9"); + // Not a valid hash, has a non-hex-digit. + t_nohash!("_ZN3foo17hg5af221e174051e9E", "foo::hg5af221e174051e9"); + } + + #[test] + fn demangle_thinlto() { + // One element, no hash. + t!("_ZN3fooE.llvm.9D1C9369", "foo"); + t!("_ZN3fooE.llvm.9D1C9369@@16", "foo"); + t_nohash!("_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9", "backtrace::foo"); + } + + #[test] + fn demangle_llvm_ir_branch_labels() { + t!("_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i", "core::slice:: for [T]>::index_mut::haf9727c2edfbc47b.exit.i.i"); + t_nohash!("_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i", "core::slice:: for [T]>::index_mut.exit.i.i"); + } + + #[test] + fn demangle_ignores_suffix_that_doesnt_look_like_a_symbol() { + t_err!("_ZN3fooE.llvm moocow"); + } + + #[test] + fn dont_panic() { + ::demangle("_ZN2222222222222222222222EE").to_string(); + ::demangle("_ZN5*70527e27.ll34csaғE").to_string(); + ::demangle("_ZN5*70527a54.ll34_$b.1E").to_string(); + ::demangle("\ + _ZN5~saäb4e\n\ + 2734cOsbE\n\ + 5usage20h)3\0\0\0\0\0\0\07e2734cOsbE\ + ").to_string(); + } + + #[test] + fn invalid_no_chop() { + t_err!("_ZNfooE"); + } + + #[test] + fn handle_assoc_types() { + t!("_ZN151_$LT$alloc..boxed..Box$LT$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$9call_once17h69e8f44b3723e1caE", " + 'a> as core::ops::function::FnOnce
>::call_once::h69e8f44b3723e1ca"); + } + + #[test] + fn handle_bang() { + t!( + "_ZN88_$LT$core..result..Result$LT$$u21$$C$$u20$E$GT$$u20$as$u20$std..process..Termination$GT$6report17hfc41d0da4a40b3e8E", + " as std::process::Termination>::report::hfc41d0da4a40b3e8" + ); + } +} diff --git a/vendor/rustc-demangle/src/lib.rs b/vendor/rustc-demangle/src/lib.rs index 150dc5153b..41bc796a3a 100644 --- a/vendor/rustc-demangle/src/lib.rs +++ b/vendor/rustc-demangle/src/lib.rs @@ -30,25 +30,25 @@ #[macro_use] extern crate std; +mod legacy; +mod v0; + use core::fmt; /// Representation of a demangled symbol name. pub struct Demangle<'a> { + style: Option>, original: &'a str, - inner: &'a str, suffix: &'a str, - valid: bool, - /// The number of ::-separated elements in the original name. - elements: usize, +} + +enum DemangleStyle<'a> { + Legacy(legacy::Demangle<'a>), + V0(v0::Demangle<'a>), } /// De-mangles a Rust symbol into a more readable version /// -/// All Rust symbols by default are mangled as they contain characters that -/// cannot be represented in all object files. The mangling mechanism is similar -/// to C++'s, but Rust has a few specifics to handle items like lifetimes in -/// symbols. -/// /// This function will take a **mangled** symbol and return a value. When printed, /// the de-mangled version will be written. If the symbol does not look like /// a mangled symbol, the original value will be written instead. @@ -62,24 +62,6 @@ pub struct Demangle<'a> { /// assert_eq!(demangle("_ZN3foo3barE").to_string(), "foo::bar"); /// assert_eq!(demangle("foo").to_string(), "foo"); /// ``` - -// All Rust symbols are in theory lists of "::"-separated identifiers. Some -// assemblers, however, can't handle these characters in symbol names. To get -// around this, we use C++-style mangling. The mangling method is: -// -// 1. Prefix the symbol with "_ZN" -// 2. For each element of the path, emit the length plus the element -// 3. End the path with "E" -// -// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar". -// -// We're the ones printing our backtraces, so we can't rely on anything else to -// demangle our symbols. It's *much* nicer to look at demangled symbols, so -// this function is implemented to give us nice pretty output. -// -// Note that this demangler isn't quite as fancy as it could be. We have lots -// of other information in our symbols like hashes, version, type information, -// etc. Additionally, this doesn't handle glue symbols at all. pub fn demangle(mut s: &str) -> Demangle { // During ThinLTO LLVM may import and rename internal symbols, so strip out // those endings first as they're one of the last manglings applied to symbol @@ -111,67 +93,17 @@ pub fn demangle(mut s: &str) -> Demangle { } } - // First validate the symbol. If it doesn't look like anything we're - // expecting, we just print it literally. Note that we must handle non-Rust - // symbols because we could have any function in the backtrace. - let mut valid = true; - let mut inner = s; - if s.len() > 4 && s.starts_with("_ZN") && s.ends_with('E') { - inner = &s[3..s.len() - 1]; - } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with('E') { - // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" - // form too. - inner = &s[2..s.len() - 1]; - } else if s.len() > 5 && s.starts_with("__ZN") && s.ends_with('E') { - // On OSX, symbols are prefixed with an extra _ - inner = &s[4..s.len() - 1]; - } else { - valid = false; - } - - // only work with ascii text - if inner.bytes().any(|c| c & 0x80 != 0) { - valid = false; - } - - let mut elements = 0; - if valid { - let mut chars = inner.chars().peekable(); - while valid { - let mut i = 0usize; - while let Some(&c) = chars.peek() { - if !c.is_digit(10) { - break - } - chars.next(); - let next = i.checked_mul(10) - .and_then(|i| i.checked_add(c as usize - '0' as usize)); - i = match next { - Some(i) => i, - None => { - valid = false; - break - } - }; - } - - if i == 0 { - valid = chars.next().is_none(); - break; - } else if chars.by_ref().take(i).count() != i { - valid = false; - } else { - elements += 1; - } - } - } - + let style = match legacy::demangle(s) { + Ok(d) => Some(DemangleStyle::Legacy(d)), + Err(()) => match v0::demangle(s) { + Ok(d) => Some(DemangleStyle::V0(d)), + Err(v0::Invalid) => None, + }, + }; Demangle { - inner: inner, - suffix: suffix, - valid: valid, - elements: elements, + style: style, original: s, + suffix: suffix, } } @@ -197,7 +129,7 @@ pub struct TryDemangleError { /// ``` pub fn try_demangle(s: &str) -> Result { let sym = demangle(s); - if sym.valid { + if sym.style.is_some() { Ok(sym) } else { Err(TryDemangleError { _priv: () }) @@ -211,11 +143,6 @@ impl<'a> Demangle<'a> { } } -// Rust hashes are hex digits with an `h` prepended. -fn is_rust_hash(s: &str) -> bool { - s.starts_with('h') && s[1..].chars().all(|c| c.is_digit(16)) -} - fn is_symbol_like(s: &str) -> bool { s.chars().all(|c| { // Once `char::is_ascii_punctuation` and `char::is_ascii_alphanumeric` @@ -247,94 +174,16 @@ fn is_ascii_punctuation(c: char) -> bool { impl<'a> fmt::Display for Demangle<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // Alright, let's do this. - if !self.valid { - return f.write_str(self.original); - } - - let mut inner = self.inner; - for element in 0..self.elements { - let mut rest = inner; - while rest.chars().next().unwrap().is_digit(10) { - rest = &rest[1..]; + match self.style { + None => try!(f.write_str(self.original)), + Some(DemangleStyle::Legacy(ref d)) => { + try!(fmt::Display::fmt(d, f)) } - let i: usize = inner[..(inner.len() - rest.len())].parse().unwrap(); - inner = &rest[i..]; - rest = &rest[..i]; - // Skip printing the hash if alternate formatting - // was requested. - if f.alternate() && element+1 == self.elements && is_rust_hash(&rest) { - break; - } - if element != 0 { - try!(f.write_str("::")); - } - if rest.starts_with("_$") { - rest = &rest[1..]; - } - while !rest.is_empty() { - if rest.starts_with('.') { - if let Some('.') = rest[1..].chars().next() { - try!(f.write_str("::")); - rest = &rest[2..]; - } else { - try!(f.write_str(".")); - rest = &rest[1..]; - } - } else if rest.starts_with('$') { - macro_rules! demangle { - ($($pat:expr => $demangled:expr),*) => ({ - $(if rest.starts_with($pat) { - try!(f.write_str($demangled)); - rest = &rest[$pat.len()..]; - } else)* - { - try!(f.write_str(rest)); - break; - } - - }) - } - - // see src/librustc/back/link.rs for these mappings - demangle! { - "$SP$" => "@", - "$BP$" => "*", - "$RF$" => "&", - "$LT$" => "<", - "$GT$" => ">", - "$LP$" => "(", - "$RP$" => ")", - "$C$" => ",", - - // in theory we can demangle any Unicode code point, but - // for simplicity we just catch the common ones. - "$u7e$" => "~", - "$u20$" => " ", - "$u27$" => "'", - "$u3d$" => "=", - "$u5b$" => "[", - "$u5d$" => "]", - "$u7b$" => "{", - "$u7d$" => "}", - "$u3b$" => ";", - "$u2b$" => "+", - "$u22$" => "\"" - } - } else { - let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') { - None => rest.len(), - Some((i, _)) => i, - }; - try!(f.write_str(&rest[..idx])); - rest = &rest[idx..]; - } + Some(DemangleStyle::V0(ref d)) => { + try!(fmt::Display::fmt(d, f)) } } - - try!(f.write_str(self.suffix)); - - Ok(()) + f.write_str(self.suffix) } } @@ -364,7 +213,14 @@ mod tests { fn ok(sym: &str, expected: &str) -> bool { match super::try_demangle(sym) { - Ok(s) => s.to_string() == expected, + Ok(s) => { + if s.to_string() == expected { + true + } else { + println!("\n{}\n!=\n{}\n", s, expected); + false + } + } Err(_) => { println!("error demangling"); false @@ -498,4 +354,12 @@ mod tests { fn handle_assoc_types() { t!("_ZN151_$LT$alloc..boxed..Box$LT$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$9call_once17h69e8f44b3723e1caE", " + 'a> as core::ops::function::FnOnce>::call_once::h69e8f44b3723e1ca"); } + + #[test] + fn handle_bang() { + t!( + "_ZN88_$LT$core..result..Result$LT$$u21$$C$$u20$E$GT$$u20$as$u20$std..process..Termination$GT$6report17hfc41d0da4a40b3e8E", + " as std::process::Termination>::report::hfc41d0da4a40b3e8" + ); + } } diff --git a/vendor/rustc-demangle/src/v0.rs b/vendor/rustc-demangle/src/v0.rs new file mode 100644 index 0000000000..8fdbe83d0c --- /dev/null +++ b/vendor/rustc-demangle/src/v0.rs @@ -0,0 +1,1067 @@ +use core::char; +use core::fmt; +use core::fmt::Display; + +/// Representation of a demangled symbol name. +pub struct Demangle<'a> { + inner: &'a str, +} + +/// De-mangles a Rust symbol into a more readable version +/// +/// This function will take a **mangled** symbol and return a value. When printed, +/// the de-mangled version will be written. If the symbol does not look like +/// a mangled symbol, the original value will be written instead. +pub fn demangle(s: &str) -> Result { + // First validate the symbol. If it doesn't look like anything we're + // expecting, we just print it literally. Note that we must handle non-Rust + // symbols because we could have any function in the backtrace. + let inner; + if s.len() > 2 && s.starts_with("_R") { + inner = &s[2..]; + } else if s.len() > 1 && s.starts_with("R") { + // On Windows, dbghelp strips leading underscores, so we accept "R..." + // form too. + inner = &s[1..]; + } else if s.len() > 3 && s.starts_with("__R") { + // On OSX, symbols are prefixed with an extra _ + inner = &s[3..]; + } else { + return Err(Invalid); + } + + // Paths always start with uppercase characters. + match inner.as_bytes()[0] { + b'A'...b'Z' => {} + _ => return Err(Invalid), + } + + // only work with ascii text + if inner.bytes().any(|c| c & 0x80 != 0) { + return Err(Invalid); + } + + // Verify that the symbol is indeed a valid path. + let mut parser = Parser { + sym: inner, + next: 0, + }; + try!(parser.skip_path()); + if parser.next < parser.sym.len() { + // Instantiating crate. + try!(parser.skip_path()); + } + if parser.next != parser.sym.len() { + return Err(Invalid); + } + + Ok(Demangle { + inner: inner, + }) +} + +impl<'s> Display for Demangle<'s> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut printer = Printer { + parser: Ok(Parser { + sym: self.inner, + next: 0, + }), + out: f, + bound_lifetime_depth: 0, + }; + printer.print_path(true) + } +} + +#[derive(PartialEq, Eq)] +pub struct Invalid; + +struct Ident<'s> { + /// ASCII part of the identifier. + ascii: &'s str, + /// Punycode insertion codes for Unicode codepoints, if any. + punycode: &'s str, +} + +const SMALL_PUNYCODE_LEN: usize = 128; + +impl<'s> Ident<'s> { + /// Attempt to decode punycode on the stack (allocation-free), + /// and pass the char slice to the closure, if successful. + /// This supports up to `SMALL_PUNYCODE_LEN` characters. + fn try_small_punycode_decode R, R>( + &self, + f: F, + ) -> Option { + let mut out = ['\0'; SMALL_PUNYCODE_LEN]; + let mut out_len = 0; + let r = self.punycode_decode(|i, c| { + // Check there's space left for another character. + try!(out.get(out_len).ok_or(())); + + // Move the characters after the insert position. + let mut j = out_len; + out_len += 1; + + while j > i { + out[j] = out[j - 1]; + j -= 1; + } + + // Insert the new character. + out[i] = c; + + Ok(()) + }); + if r.is_ok() { + Some(f(&out[..out_len])) + } else { + None + } + } + + /// Decode punycode as insertion positions and characters + /// and pass them to the closure, which can return `Err(())` + /// to stop the decoding process. + fn punycode_decode Result<(), ()>>( + &self, + mut insert: F, + ) -> Result<(), ()> { + let mut punycode_bytes = self.punycode.bytes().peekable(); + if punycode_bytes.peek().is_none() { + return Err(()); + } + + let mut len = 0; + + // Populate initial output from ASCII fragment. + for c in self.ascii.chars() { + try!(insert(len, c)); + len += 1; + } + + // Punycode parameters and initial state. + let base = 36; + let t_min = 1; + let t_max = 26; + let skew = 38; + let mut damp = 700; + let mut bias = 72; + let mut i: usize = 0; + let mut n: usize = 0x80; + + loop { + // Read one delta value. + let mut delta: usize = 0; + let mut w = 1; + let mut k: usize = 0; + loop { + use core::cmp::{min, max}; + + k += base; + let t = min(max(k.saturating_sub(bias), t_min), t_max); + + let d = match punycode_bytes.next() { + Some(d @ b'a'...b'z') => d - b'a', + Some(d @ b'0'...b'9') => 26 + (d - b'0'), + _ => return Err(()), + }; + let d = d as usize; + delta = try!(delta.checked_add( + try!(d.checked_mul(w).ok_or(())) + ).ok_or(())); + if d < t { + break; + } + w = try!(w.checked_mul(base - t).ok_or(())); + } + + // Compute the new insert position and character. + len += 1; + i = try!(i.checked_add(delta).ok_or(())); + n = try!(n.checked_add(i / len).ok_or(())); + i %= len; + + let n_u32 = n as u32; + let c = if n_u32 as usize == n { + try!(char::from_u32(n_u32).ok_or(())) + } else { + return Err(()); + }; + + // Insert the new character and increment the insert position. + try!(insert(i, c)); + i += 1; + + // If there are no more deltas, decoding is complete. + if punycode_bytes.peek().is_none() { + return Ok(()); + } + + // Perform bias adaptation. + delta /= damp; + damp = 2; + + delta += delta / len; + let mut k = 0; + while delta > ((base - t_min) * t_max) / 2 { + delta /= base - t_min; + k += base; + } + bias = k + ((base - t_min + 1) * delta) / (delta + skew); + } + } +} + +impl<'s> Display for Ident<'s> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.try_small_punycode_decode(|chars| { + for &c in chars { + try!(c.fmt(f)); + } + Ok(()) + }).unwrap_or_else(|| { + if !self.punycode.is_empty() { + try!(f.write_str("punycode{")); + + // Reconstruct a standard Punycode encoding, + // by using `-` as the separator. + if !self.ascii.is_empty() { + try!(f.write_str(self.ascii)); + try!(f.write_str("-")); + } + try!(f.write_str(self.punycode)); + + f.write_str("}") + } else { + f.write_str(self.ascii) + } + }) + } +} + +fn basic_type(tag: u8) -> Option<&'static str> { + Some(match tag { + b'b' => "bool", + b'c' => "char", + b'e' => "str", + b'u' => "()", + b'a' => "i8", + b's' => "i16", + b'l' => "i32", + b'x' => "i64", + b'n' => "i128", + b'i' => "isize", + b'h' => "u8", + b't' => "u16", + b'm' => "u32", + b'y' => "u64", + b'o' => "u128", + b'j' => "usize", + b'f' => "f32", + b'd' => "f64", + b'z' => "!", + b'p' => "_", + b'v' => "...", + + _ => return None, + }) +} + +struct Parser<'s> { + sym: &'s str, + next: usize, +} + +impl<'s> Parser<'s> { + fn peek(&self) -> Option { + self.sym.as_bytes().get(self.next).cloned() + } + + fn eat(&mut self, b: u8) -> bool { + if self.peek() == Some(b) { + self.next += 1; + true + } else { + false + } + } + + fn next(&mut self) -> Result { + let b = try!(self.peek().ok_or(Invalid)); + self.next += 1; + Ok(b) + } + + fn hex_nibbles(&mut self) -> Result<&'s str, Invalid> { + let start = self.next; + loop { + match try!(self.next()) { + b'0'...b'9' | b'a'...b'f' => {} + b'_' => break, + _ => return Err(Invalid), + } + } + Ok(&self.sym[start..self.next - 1]) + } + + fn digit_10(&mut self) -> Result { + let d = match self.peek() { + Some(d @ b'0'...b'9') => d - b'0', + _ => return Err(Invalid), + }; + self.next += 1; + Ok(d) + } + + fn digit_62(&mut self) -> Result { + let d = match self.peek() { + Some(d @ b'0'...b'9') => d - b'0', + Some(d @ b'a'...b'z') => 10 + (d - b'a'), + Some(d @ b'A'...b'Z') => 10 + 26 + (d - b'A'), + _ => return Err(Invalid), + }; + self.next += 1; + Ok(d) + } + + fn integer_62(&mut self) -> Result { + if self.eat(b'_') { + return Ok(0); + } + + let mut x: u64 = 0; + while !self.eat(b'_') { + let d = try!(self.digit_62()) as u64; + x = try!(x.checked_mul(62).ok_or(Invalid)); + x = try!(x.checked_add(d).ok_or(Invalid)); + } + x.checked_add(1).ok_or(Invalid) + } + + fn opt_integer_62(&mut self, tag: u8) -> Result { + if !self.eat(tag) { + return Ok(0); + } + try!(self.integer_62()).checked_add(1).ok_or(Invalid) + } + + fn disambiguator(&mut self) -> Result { + self.opt_integer_62(b's') + } + + fn namespace(&mut self) -> Result, Invalid> { + match try!(self.next()) { + // Special namespaces, like closures and shims. + ns @ b'A'...b'Z' => Ok(Some(ns as char)), + + // Implementation-specific/unspecified namespaces. + b'a'...b'z' => Ok(None), + + _ => Err(Invalid), + } + } + + fn backref(&mut self) -> Result, Invalid> { + let s_start = self.next - 1; + let i = try!(self.integer_62()); + if i >= s_start as u64 { + return Err(Invalid); + } + Ok(Parser { + sym: self.sym, + next: i as usize, + }) + } + + fn ident(&mut self) -> Result, Invalid> { + let is_punycode = self.eat(b'u'); + let mut len = try!(self.digit_10()) as usize; + if len != 0 { + loop { + match self.digit_10() { + Ok(d) => { + len = try!(len.checked_mul(10).ok_or(Invalid)); + len = try!(len.checked_add(d as usize).ok_or(Invalid)); + } + Err(Invalid) => break, + } + } + } + + // Skip past the optional `_` separator. + self.eat(b'_'); + + let start = self.next; + self.next = try!(self.next.checked_add(len).ok_or(Invalid)); + if self.next > self.sym.len() { + return Err(Invalid); + } + + let ident = &self.sym[start..self.next]; + + if is_punycode { + let ident = match ident.bytes().rposition(|b| b == b'_') { + Some(i) => Ident { + ascii: &ident[..i], + punycode: &ident[i + 1..], + }, + None => Ident { + ascii: "", + punycode: ident, + }, + }; + if ident.punycode.is_empty() { + return Err(Invalid); + } + Ok(ident) + } else { + Ok(Ident { + ascii: ident, + punycode: "", + }) + } + } + + fn skip_path(&mut self) -> Result<(), Invalid> { + match try!(self.next()) { + b'C' => { + try!(self.disambiguator()); + try!(self.ident()); + } + b'N' => { + try!(self.namespace()); + try!(self.skip_path()); + try!(self.disambiguator()); + try!(self.ident()); + } + b'M' => { + try!(self.disambiguator()); + try!(self.skip_path()); + try!(self.skip_type()); + } + b'X' => { + try!(self.disambiguator()); + try!(self.skip_path()); + try!(self.skip_type()); + try!(self.skip_path()); + } + b'Y' => { + try!(self.skip_type()); + try!(self.skip_path()); + } + b'I' => { + try!(self.skip_path()); + while !self.eat(b'E') { + try!(self.skip_generic_arg()); + } + } + b'B' => { + try!(self.backref()); + } + _ => return Err(Invalid), + } + Ok(()) + } + + fn skip_generic_arg(&mut self) -> Result<(), Invalid> { + if self.eat(b'L') { + try!(self.integer_62()); + Ok(()) + } else if self.eat(b'K') { + self.skip_const() + } else { + self.skip_type() + } + } + + fn skip_type(&mut self) -> Result<(), Invalid> { + match try!(self.next()) { + tag if basic_type(tag).is_some() => {} + + b'R' | b'Q' => { + if self.eat(b'L') { + try!(self.integer_62()); + } + try!(self.skip_type()); + } + b'P' | b'O' | b'S' => try!(self.skip_type()), + b'A' => { + try!(self.skip_type()); + try!(self.skip_const()); + } + b'T' => while !self.eat(b'E') { + try!(self.skip_type()); + }, + b'F' => { + let _binder = try!(self.opt_integer_62(b'G')); + let _is_unsafe = self.eat(b'U'); + if self.eat(b'K') { + let c_abi = self.eat(b'C'); + if !c_abi { + let abi = try!(self.ident()); + if abi.ascii.is_empty() || !abi.punycode.is_empty() { + return Err(Invalid); + } + } + } + while !self.eat(b'E') { + try!(self.skip_type()); + } + try!(self.skip_type()); + } + b'D' => { + let _binder = try!(self.opt_integer_62(b'G')); + while !self.eat(b'E') { + try!(self.skip_path()); + while self.eat(b'p') { + try!(self.ident()); + try!(self.skip_type()); + } + } + if !self.eat(b'L') { + return Err(Invalid); + } + try!(self.integer_62()); + } + b'B' => { + try!(self.backref()); + } + _ => { + // Go back to the tag, so `skip_path` also sees it. + self.next -= 1; + try!(self.skip_path()); + } + } + Ok(()) + } + + fn skip_const(&mut self) -> Result<(), Invalid> { + if self.eat(b'B') { + try!(self.backref()); + return Ok(()); + } + + match try!(self.next()) { + // Unsigned integer types. + b'h' | b't' | b'm' | b'y' | b'o' | b'j' => {} + + _ => return Err(Invalid), + } + + if self.eat(b'p') { + return Ok(()); + } + try!(self.hex_nibbles()); + Ok(()) + } +} + +struct Printer<'a, 'b: 'a, 's> { + parser: Result, Invalid>, + out: &'a mut fmt::Formatter<'b>, + bound_lifetime_depth: u32, +} + +/// Mark the parser as errored, print `?` and return early. +/// This allows callers to keep printing the approximate +/// syntax of the path/type/const, despite having errors. +/// E.g. `Vec<[(A, ?); ?]>` instead of `Vec<[(A, ?`. +macro_rules! invalid { + ($printer:ident) => {{ + $printer.parser = Err(Invalid); + return $printer.out.write_str("?"); + }} +} + +/// Call a parser method (if the parser hasn't errored yet), +/// and mark the parser as errored if it returns `Err(Invalid)`. +/// +/// If the parser errored, before or now, prints `?`, and +/// returns early the current function (see `invalid!` above). +macro_rules! parse { + ($printer:ident, $method:ident $(($($arg:expr),*))*) => { + match $printer.parser_mut().and_then(|p| p.$method($($($arg),*)*)) { + Ok(x) => x, + Err(Invalid) => invalid!($printer), + } + }; +} + +impl<'a, 'b, 's> Printer<'a, 'b, 's> { + fn parser_mut<'c>(&'c mut self) -> Result<&'c mut Parser<'s>, Invalid> { + self.parser.as_mut().map_err(|_| Invalid) + } + + /// Eat the given character from the parser, + /// returning `false` if the parser errored. + fn eat(&mut self, b: u8) -> bool { + self.parser_mut().map(|p| p.eat(b)) == Ok(true) + } + + /// Return a nested parser for a backref. + fn backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's> { + Printer { + parser: self.parser_mut().and_then(|p| p.backref()), + out: self.out, + bound_lifetime_depth: self.bound_lifetime_depth, + } + } + + /// Print the lifetime according to the previously decoded index. + /// An index of `0` always refers to `'_`, but starting with `1`, + /// indices refer to late-bound lifetimes introduced by a binder. + fn print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result { + try!(self.out.write_str("'")); + if lt == 0 { + return self.out.write_str("_"); + } + match (self.bound_lifetime_depth as u64).checked_sub(lt) { + Some(depth) => { + // Try to print lifetimes alphabetically first. + if depth < 26 { + let c = (b'a' + depth as u8) as char; + c.fmt(self.out) + } else { + // Use `'_123` after running out of letters. + try!(self.out.write_str("_")); + depth.fmt(self.out) + } + } + None => invalid!(self), + } + } + + /// Optionally enter a binder ('G') for late-bound lifetimes, + /// printing e.g. `for<'a, 'b> ` before calling the closure, + /// and make those lifetimes visible to it (via depth level). + fn in_binder(&mut self, f: F) -> fmt::Result + where F: FnOnce(&mut Self) -> fmt::Result, + { + let bound_lifetimes = parse!(self, opt_integer_62(b'G')); + + if bound_lifetimes > 0 { + try!(self.out.write_str("for<")); + for i in 0..bound_lifetimes { + if i > 0 { + try!(self.out.write_str(", ")); + } + self.bound_lifetime_depth += 1; + try!(self.print_lifetime_from_index(1)); + } + try!(self.out.write_str("> ")); + } + + let r = f(self); + + // Restore `bound_lifetime_depth` to the previous value. + self.bound_lifetime_depth -= bound_lifetimes as u32; + + r + } + + /// Print list elements using the given closure and separator, + /// until the end of the list ('E') is found, or the parser errors. + /// Returns the number of elements printed. + fn print_sep_list(&mut self, f: F, sep: &str) -> Result + where F: Fn(&mut Self) -> fmt::Result, + { + let mut i = 0; + while self.parser.is_ok() && !self.eat(b'E') { + if i > 0 { + try!(self.out.write_str(sep)); + } + try!(f(self)); + i += 1; + } + Ok(i) + } + + fn print_path(&mut self, in_value: bool) -> fmt::Result { + let tag = parse!(self, next); + match tag { + b'C' => { + let dis = parse!(self, disambiguator); + let name = parse!(self, ident); + + try!(name.fmt(self.out)); + if !self.out.alternate() { + try!(self.out.write_str("[")); + try!(fmt::LowerHex::fmt(&dis, self.out)); + try!(self.out.write_str("]")); + } + } + b'N' => { + let ns = parse!(self, namespace); + + try!(self.print_path(in_value)); + + let dis = parse!(self, disambiguator); + let name = parse!(self, ident); + + match ns { + // Special namespaces, like closures and shims. + Some(ns) => { + try!(self.out.write_str("::{")); + match ns { + 'C' => try!(self.out.write_str("closure")), + 'S' => try!(self.out.write_str("shim")), + _ => try!(ns.fmt(self.out)), + } + if !name.ascii.is_empty() || !name.punycode.is_empty() { + try!(self.out.write_str(":")); + try!(name.fmt(self.out)); + } + try!(self.out.write_str("#")); + try!(dis.fmt(self.out)); + try!(self.out.write_str("}")); + } + + // Implementation-specific/unspecified namespaces. + None => { + if !name.ascii.is_empty() || !name.punycode.is_empty() { + try!(self.out.write_str("::")); + try!(name.fmt(self.out)); + } + } + } + } + b'M' | b'X' | b'Y' => { + if tag != b'Y' { + // Ignore the `impl`'s own path. + parse!(self, disambiguator); + parse!(self, skip_path); + } + + try!(self.out.write_str("<")); + try!(self.print_type()); + if tag != b'M' { + try!(self.out.write_str(" as ")); + try!(self.print_path(false)); + } + try!(self.out.write_str(">")); + } + b'I' => { + try!(self.print_path(in_value)); + if in_value { + try!(self.out.write_str("::")); + } + try!(self.out.write_str("<")); + try!(self.print_sep_list(Self::print_generic_arg, ", ")); + try!(self.out.write_str(">")); + } + b'B' => { + try!(self.backref_printer().print_path(in_value)); + } + _ => invalid!(self), + } + Ok(()) + } + + fn print_generic_arg(&mut self) -> fmt::Result { + if self.eat(b'L') { + let lt = parse!(self, integer_62); + self.print_lifetime_from_index(lt) + } else if self.eat(b'K') { + self.print_const() + } else { + self.print_type() + } + } + + fn print_type(&mut self) -> fmt::Result { + let tag = parse!(self, next); + + match basic_type(tag) { + Some(ty) => return self.out.write_str(ty), + None => {} + } + + match tag { + b'R' | b'Q' => { + try!(self.out.write_str("&")); + if self.eat(b'L') { + let lt = parse!(self, integer_62); + if lt != 0 { + try!(self.print_lifetime_from_index(lt)); + try!(self.out.write_str(" ")); + } + } + if tag != b'R' { + try!(self.out.write_str("mut ")); + } + try!(self.print_type()); + } + + b'P' | b'O' => { + try!(self.out.write_str("*")); + if tag != b'P' { + try!(self.out.write_str("mut ")); + } else { + try!(self.out.write_str("const ")); + } + try!(self.print_type()); + } + + b'A' | b'S' => { + try!(self.out.write_str("[")); + try!(self.print_type()); + if tag == b'A' { + try!(self.out.write_str("; ")); + try!(self.print_const()); + } + try!(self.out.write_str("]")); + } + b'T' => { + try!(self.out.write_str("(")); + let count = try!(self.print_sep_list(Self::print_type, ", ")); + if count == 1 { + try!(self.out.write_str(",")); + } + try!(self.out.write_str(")")); + } + b'F' => try!(self.in_binder(|this| { + let is_unsafe = this.eat(b'U'); + let abi = if this.eat(b'K') { + if this.eat(b'C') { + Some("C") + } else { + let abi = parse!(this, ident); + if abi.ascii.is_empty() || !abi.punycode.is_empty() { + invalid!(this); + } + Some(abi.ascii) + } + } else { + None + }; + + if is_unsafe { + try!(this.out.write_str("unsafe ")); + } + + match abi { + Some(abi) => { + try!(this.out.write_str("extern \"")); + + // If the ABI had any `-`, they were replaced with `_`, + // so the parts between `_` have to be re-joined with `-`. + let mut parts = abi.split('_'); + try!(this.out.write_str(parts.next().unwrap())); + for part in parts { + try!(this.out.write_str("-")); + try!(this.out.write_str(part)); + } + + try!(this.out.write_str("\" ")); + } + None => {} + } + + try!(this.out.write_str("fn(")); + try!(this.print_sep_list(Self::print_type, ", ")); + try!(this.out.write_str(")")); + + if this.eat(b'u') { + // Skip printing the return type if it's 'u', i.e. `()`. + } else { + try!(this.out.write_str(" -> ")); + try!(this.print_type()); + } + + Ok(()) + })), + b'D' => { + try!(self.out.write_str("dyn ")); + try!(self.in_binder(|this| { + try!(this.print_sep_list(Self::print_dyn_trait, " + ")); + Ok(()) + })); + + if !self.eat(b'L') { + invalid!(self); + } + let lt = parse!(self, integer_62); + if lt != 0 { + try!(self.out.write_str(" + ")); + try!(self.print_lifetime_from_index(lt)); + } + } + b'B' => { + try!(self.backref_printer().print_type()); + } + _ => { + // Go back to the tag, so `print_path` also sees it. + let _ = self.parser_mut().map(|p| p.next -= 1); + try!(self.print_path(false)); + } + } + Ok(()) + } + + /// A trait in a trait object may have some "existential projections" + /// (i.e. associated type bindings) after it, which should be printed + /// in the `<...>` of the trait, e.g. `dyn Trait`. + /// To this end, this method will keep the `<...>` of an 'I' path + /// open, by omitting the `>`, and return `Ok(true)` in that case. + fn print_path_maybe_open_generics(&mut self) -> Result { + if self.eat(b'B') { + self.backref_printer().print_path_maybe_open_generics() + } else if self.eat(b'I') { + try!(self.print_path(false)); + try!(self.out.write_str("<")); + try!(self.print_sep_list(Self::print_generic_arg, ", ")); + Ok(true) + } else { + try!(self.print_path(false)); + Ok(false) + } + } + + fn print_dyn_trait(&mut self) -> fmt::Result { + let mut open = try!(self.print_path_maybe_open_generics()); + + while self.eat(b'p') { + if !open { + try!(self.out.write_str("<")); + open = true; + } else { + try!(self.out.write_str(", ")); + } + + let name = parse!(self, ident); + try!(name.fmt(self.out)); + try!(self.out.write_str(" = ")); + try!(self.print_type()); + } + + if open { + try!(self.out.write_str(">")); + } + + Ok(()) + } + + fn print_const(&mut self) -> fmt::Result { + if self.eat(b'B') { + return self.backref_printer().print_const(); + } + + let ty_tag = parse!(self, next); + let ty = match ty_tag { + // Unsigned integer types. + b'h' | b't' | b'm' | b'y' | b'o' | b'j' => { + basic_type(ty_tag).unwrap() + } + + _ => invalid!(self), + }; + + + if self.eat(b'p') { + try!(self.out.write_str("_")); + } else { + try!(self.print_const_uint()); + } + + if !self.out.alternate() { + try!(self.out.write_str(": ")); + try!(self.out.write_str(ty)); + } + + Ok(()) + } + + fn print_const_uint(&mut self) -> fmt::Result { + let hex = parse!(self, hex_nibbles); + + // Print anything that doesn't fit in `u64` verbatim. + if hex.len() > 16 { + try!(self.out.write_str("0x")); + return self.out.write_str(hex); + } + + let mut v = 0; + for c in hex.chars() { + v = (v << 4) | (c.to_digit(16).unwrap() as u64); + } + v.fmt(self.out) + } +} + +#[cfg(test)] +mod tests { + macro_rules! t_nohash { + ($a:expr, $b:expr) => ({ + assert_eq!(format!("{:#}", ::demangle($a)), $b); + }) + } + macro_rules! t_nohash_type { + ($a:expr, $b:expr) => ( + t_nohash!(concat!("_RMC0", $a), concat!("<", $b, ">")) + ) + } + + #[test] + fn demangle_crate_with_leading_digit() { + t_nohash!( + "_RNvC6_123foo3bar", + "123foo::bar" + ); + } + + #[test] + fn demangle_utf8_idents() { + t_nohash!( + "_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y", + "utf8_idents::საჭმელად_გემრიელი_სადილი" + ); + } + + #[test] + fn demangle_closure() { + t_nohash!( + "_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_", + "cc::spawn::{closure#0}::{closure#0}" + ); + t_nohash!( + "_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_", + " as core::iter::iterator::Iterator>::rposition::::{closure#0}" + ); + } + + #[test] + fn demangle_dyn_trait() { + t_nohash!( + "_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std", + "alloc::alloc::box_free::>" + ); + } + + #[test] + fn demangle_const_generics() { + // NOTE(eddyb) this was hand-written, before rustc had working + // const generics support (but the mangling format did include them). + t_nohash_type!( + "INtC8arrayvec8ArrayVechKj7b_E", + "arrayvec::ArrayVec" + ); + } + + #[test] + fn demangle_exponential_explosion() { + // NOTE(eddyb) because of the prefix added by `t_nohash_type!` is + // 3 bytes long, `B2_` refers to the start of the type, not `B_`. + // 6 backrefs (`B8_E` through `B3_E`) result in 2^6 = 64 copies of `_`. + // Also, because the `p` (`_`) type is after all of the starts of the + // backrefs, it can be replaced with any other type, independently. + t_nohash_type!( + concat!("TTTTTT", "p", "B8_E", "B7_E", "B6_E", "B5_E", "B4_E", "B3_E"), + "((((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \ + ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))), \ + (((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \ + ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))))" + ); + } +} diff --git a/vendor/serde/.cargo-checksum.json b/vendor/serde/.cargo-checksum.json index a7720c7afb..855da1633f 100644 --- a/vendor/serde/.cargo-checksum.json +++ b/vendor/serde/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"f8bedfd6ae0fa2f6bac5f7d93d0cf2f0d9ec14ddd92faf09325b6b93cab7702a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"c4218d07d775c036cd50495b0354c5b59435472b12e159042cacb30b6ef1a7c1","build.rs":"dcfb811e5852fd6151435382d6a3682c0e0b6cb2ca652bc21e5f4d63edecf14b","crates-io.md":"8dce715dfbd2e9bbdd87e401d1f7974a60089f0673f7a84f4c5d840411075d14","src/de/from_primitive.rs":"058fa17313ed3a9c29ec04c6ec67f21a756f6f28cdeb4b0dfcd7012b3e702d0b","src/de/ignored_any.rs":"3224804e5337b978c0558e132c8c5fcdaa303ed7adfd9eab2767f9c22c4d93b0","src/de/impls.rs":"32edb706d85539b5524b61585f43a2db0ac392692747957b1747fe1db1b204f9","src/de/mod.rs":"75655cc2fdff2d48f6dbaa20a516ee3c0f0f590b9f7f276b6dad613a17af646a","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"00098db25f3519bbc0883739987b65fc96b3f4990fc331321245ec8819f4f942","src/export.rs":"dceb648800cd6a4ee651259a203c6d98bffe768b943f090e4a06ff0c1cfc701f","src/integer128.rs":"1bf9e18047a4a3f95a43b8d253e4f844b6be62e71684e47d980582462bce4223","src/lib.rs":"6f247ab0c867e74315c9832ae3d76bb8aed99c59c9dbdf325f9eda119d29d03b","src/macros.rs":"08d8ec8705a31312915a5536e746ba61bf0b372d414dec78ed155e14ca658bae","src/private/de.rs":"26df85eaa862a7f6c6ddfd25ed0cc86851bd93440fbbc840e8ee2750a143b7d2","src/private/macros.rs":"ebb6affd4c89e3b5f9a42e03f8b7d966bc588875e9b44e962d0b7aba7f80a10f","src/private/mod.rs":"f8f2cd5edbfc26c268b34cdb89db1b34e6348f81384f03d18532e7568575006d","src/private/ser.rs":"946bf9910bb646a4c1732fd17f8c98db2515fe23edeb6e622e3618ff4de46b33","src/ser/impls.rs":"1d3402f74cf946798d004c6d7a35d7171f733a904b97cabeb5375e18329a8a9c","src/ser/impossible.rs":"4fb8de72d77bc8518d9c3f7dfcfcdc84e551aee6b9ee8cd33a0ee6fed4dff753","src/ser/mod.rs":"e41015436dbde7586a5700e7a56325c40082717e01331bb72d173c8c60ceb7ca"},"package":"6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6"} \ No newline at end of file +{"files":{"Cargo.toml":"9f1e33b4b64aefd1513f71b767ce2c8d77b3ad0ec94490f4258a111e0380c587","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3760f279854d1ca296894756ebd4d8bc91fe164874aa4c17db522843a9725f8e","build.rs":"36983e7377af4e76eba9c8745e0d58c1668afaf651abf4ba53d203f985593f32","crates-io.md":"131dee2d4beaf83485aed22942b98815ef65af9bcfb65f02b5b90c59b8bc7b8b","src/de/from_primitive.rs":"058fa17313ed3a9c29ec04c6ec67f21a756f6f28cdeb4b0dfcd7012b3e702d0b","src/de/ignored_any.rs":"3c199f3e4c3f8775ab30439c6868b61aa0a32fa23232b218afb94d1aadb15f0a","src/de/impls.rs":"75a798b149c690ef197d3f190c95f42a2bc0a8f7b3bd9f689f7faae02c0e9403","src/de/mod.rs":"76161f9f86b1589495681da619a6785561b587c27c62724fe960b630be69c564","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"a878f6bdd57d25b0b93bfc6288ed1e46c50870dc8703748b6fbb8c0965a6b586","src/export.rs":"1519d8bf2d18368eb0a394e1aceff74e092922902a966f388b74fddecdbeb5f9","src/integer128.rs":"f8298a559f1fae7579819cb68f6cba8c01cdda11737cf1fb498bf52810c130b6","src/lib.rs":"cdb28f42ebc35a886f5b380190f8339d315cf8c75e356fd5d60264fa4497bcac","src/macros.rs":"f18fc25c5fb857238bf119cdee5c7987a8584dea69c51f27ca718b7dfd871d0f","src/private/de.rs":"2a4b0b7145135b1116f7b0af4adebe74b7d3aa4cc96896584066a654aa4b6c6c","src/private/macros.rs":"ebb6affd4c89e3b5f9a42e03f8b7d966bc588875e9b44e962d0b7aba7f80a10f","src/private/mod.rs":"f8f2cd5edbfc26c268b34cdb89db1b34e6348f81384f03d18532e7568575006d","src/private/ser.rs":"946bf9910bb646a4c1732fd17f8c98db2515fe23edeb6e622e3618ff4de46b33","src/ser/impls.rs":"1a6598433a22d2672f743619e4ec99c55378d9283f26783ade02dd2ce4acf892","src/ser/impossible.rs":"3dd0e165b88fc67e698e675f16569b91fab9e054caa4c3e1997f929ba364fe90","src/ser/mod.rs":"6fac442413315d14b60fb62d9298c857d2b93276dc8d03729db44bf8fb9a1ec5"},"package":"32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be"} \ No newline at end of file diff --git a/vendor/serde/Cargo.toml b/vendor/serde/Cargo.toml index 7021d92bcf..572c27db55 100644 --- a/vendor/serde/Cargo.toml +++ b/vendor/serde/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "serde" -version = "1.0.82" +version = "1.0.92" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" include = ["Cargo.toml", "build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] @@ -22,8 +22,10 @@ documentation = "https://docs.serde.rs/serde/" readme = "crates-io.md" keywords = ["serde", "serialization", "no_std"] categories = ["encoding"] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/serde-rs/serde" +[package.metadata.playground] +features = ["derive", "rc"] [dependencies.serde_derive] version = "1.0" optional = true diff --git a/vendor/serde/README.md b/vendor/serde/README.md index 77de3a4a26..db5fa09d7a 100644 --- a/vendor/serde/README.md +++ b/vendor/serde/README.md @@ -25,19 +25,17 @@ You may be looking for:
Click to show Cargo.toml. -Run this code in the playground. +Run this code in the playground. ```toml [dependencies] # The core APIs, including the Serialize and Deserialize traits. Always -# required when using Serde. -serde = "1.0" - -# Support for #[derive(Serialize, Deserialize)]. Required if you want Serde -# to work for structs and enums defined in your crate. -serde_derive = "1.0" +# required when using Serde. The "derive" feature is only required when +# using #[derive(Serialize, Deserialize)] to make Serde work with structs +# and enums defined in your crate. +serde = { version = "1.0", features = ["derive"] } # Each data format lives in its own crate; the sample code below uses JSON # but you may be using a different one. @@ -48,11 +46,7 @@ serde_json = "1.0"

```rust -#[macro_use] -extern crate serde_derive; - -extern crate serde; -extern crate serde_json; +use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { @@ -87,19 +81,19 @@ good response, we are happy to respond to [GitHub issues][issues] as well. [irc]: https://wiki.mozilla.org/IRC [issues]: https://github.com/serde-rs/serde/issues/new/choose -## License - -Serde is licensed under either of +
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or - http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) +#### License -at your option. + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + -### Contribution +
+ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + diff --git a/vendor/serde/build.rs b/vendor/serde/build.rs index c616d181fb..e27e2f34f0 100644 --- a/vendor/serde/build.rs +++ b/vendor/serde/build.rs @@ -14,6 +14,21 @@ fn main() { let target = env::var("TARGET").unwrap(); let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten"; + // std::collections::Bound was stabilized in Rust 1.17 + // but it was moved to core::ops later in Rust 1.26: + // https://doc.rust-lang.org/core/ops/enum.Bound.html + if minor >= 26 { + println!("cargo:rustc-cfg=ops_bound"); + } else if minor >= 17 && cfg!(feature = "std") { + println!("cargo:rustc-cfg=collections_bound"); + } + + // core::cmp::Reverse stabilized in Rust 1.19: + // https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html + if minor >= 19 { + println!("cargo:rustc-cfg=core_reverse"); + } + // CString::into_boxed_c_str stabilized in Rust 1.20: // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str if minor >= 20 { diff --git a/vendor/serde/crates-io.md b/vendor/serde/crates-io.md index d63c4ba9f7..3c6caa1a11 100644 --- a/vendor/serde/crates-io.md +++ b/vendor/serde/crates-io.md @@ -16,11 +16,7 @@ You may be looking for: ## Serde in action ```rust -#[macro_use] -extern crate serde_derive; - -extern crate serde; -extern crate serde_json; +use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { diff --git a/vendor/serde/src/de/ignored_any.rs b/vendor/serde/src/de/ignored_any.rs index 1c2064df63..855d68e1ae 100644 --- a/vendor/serde/src/de/ignored_any.rs +++ b/vendor/serde/src/de/ignored_any.rs @@ -8,7 +8,7 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; /// any type, except that it does not store any information about the data that /// gets deserialized. /// -/// ```rust +/// ```edition2018 /// use std::fmt; /// use std::marker::PhantomData; /// @@ -21,7 +21,7 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; /// /// /// /// For example to deserialize only the element at index 3: /// /// -/// /// ```rust +/// /// ``` /// /// NthElement::new(3).deserialize(deserializer) /// /// ``` /// pub struct NthElement { diff --git a/vendor/serde/src/de/impls.rs b/vendor/serde/src/de/impls.rs index 9553166143..1d4c318784 100644 --- a/vendor/serde/src/de/impls.rs +++ b/vendor/serde/src/de/impls.rs @@ -578,6 +578,9 @@ macro_rules! forwarded_impl { #[cfg(all(feature = "std", de_boxed_c_str))] forwarded_impl!((), Box, CString::into_boxed_c_str); +#[cfg(core_reverse)] +forwarded_impl!((T), Reverse, Reverse); + //////////////////////////////////////////////////////////////////////////////// struct OptionVisitor { @@ -962,7 +965,7 @@ impl<'de, T> Deserialize<'de> for [T; 0] { } macro_rules! array_impls { - ($($len:expr => ($($n:tt $name:ident)+))+) => { + ($($len:expr => ($($n:tt)+))+) => { $( impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> where @@ -979,14 +982,12 @@ macro_rules! array_impls { where A: SeqAccess<'de>, { - $( - let $name = match try!(seq.next_element()) { + Ok([$( + match try!(seq.next_element()) { Some(val) => val, None => return Err(Error::invalid_length($n, &self)), - }; - )+ - - Ok([$($name),+]) + } + ),+]) } } @@ -1042,38 +1043,38 @@ macro_rules! array_impls { } array_impls! { - 1 => (0 a) - 2 => (0 a 1 b) - 3 => (0 a 1 b 2 c) - 4 => (0 a 1 b 2 c 3 d) - 5 => (0 a 1 b 2 c 3 d 4 e) - 6 => (0 a 1 b 2 c 3 d 4 e 5 f) - 7 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g) - 8 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h) - 9 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i) - 10 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j) - 11 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k) - 12 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l) - 13 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m) - 14 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n) - 15 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o) - 16 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p) - 17 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q) - 18 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r) - 19 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s) - 20 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t) - 21 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u) - 22 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v) - 23 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w) - 24 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x) - 25 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y) - 26 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z) - 27 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa) - 28 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab) - 29 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac) - 30 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad) - 31 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae) - 32 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae 31 af) + 1 => (0) + 2 => (0 1) + 3 => (0 1 2) + 4 => (0 1 2 3) + 5 => (0 1 2 3 4) + 6 => (0 1 2 3 4 5) + 7 => (0 1 2 3 4 5 6) + 8 => (0 1 2 3 4 5 6 7) + 9 => (0 1 2 3 4 5 6 7 8) + 10 => (0 1 2 3 4 5 6 7 8 9) + 11 => (0 1 2 3 4 5 6 7 8 9 10) + 12 => (0 1 2 3 4 5 6 7 8 9 10 11) + 13 => (0 1 2 3 4 5 6 7 8 9 10 11 12) + 14 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13) + 15 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14) + 16 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + 17 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) + 18 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17) + 19 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18) + 20 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19) + 21 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) + 22 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21) + 23 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22) + 24 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23) + 25 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24) + 26 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25) + 27 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26) + 28 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27) + 29 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28) + 30 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29) + 31 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30) + 32 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) } //////////////////////////////////////////////////////////////////////////////// @@ -2269,6 +2270,117 @@ mod range { //////////////////////////////////////////////////////////////////////////////// +#[cfg(any(ops_bound, collections_bound))] +impl<'de, T> Deserialize<'de> for Bound +where + T: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + enum Field { + Unbounded, + Included, + Excluded, + } + + impl<'de> Deserialize<'de> for Field { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = Field; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("`Unbounded`, `Included` or `Excluded`") + } + + fn visit_u32(self, value: u32) -> Result + where + E: Error, + { + match value { + 0 => Ok(Field::Unbounded), + 1 => Ok(Field::Included), + 2 => Ok(Field::Excluded), + _ => Err(Error::invalid_value( + Unexpected::Unsigned(value as u64), + &self, + )), + } + } + + fn visit_str(self, value: &str) -> Result + where + E: Error, + { + match value { + "Unbounded" => Ok(Field::Unbounded), + "Included" => Ok(Field::Included), + "Excluded" => Ok(Field::Excluded), + _ => Err(Error::unknown_variant(value, VARIANTS)), + } + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + E: Error, + { + match value { + b"Unbounded" => Ok(Field::Unbounded), + b"Included" => Ok(Field::Included), + b"Excluded" => Ok(Field::Excluded), + _ => match str::from_utf8(value) { + Ok(value) => Err(Error::unknown_variant(value, VARIANTS)), + Err(_) => { + Err(Error::invalid_value(Unexpected::Bytes(value), &self)) + } + }, + } + } + } + + deserializer.deserialize_identifier(FieldVisitor) + } + } + + struct BoundVisitor(PhantomData>); + + impl<'de, T> Visitor<'de> for BoundVisitor + where + T: Deserialize<'de>, + { + type Value = Bound; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("enum Bound") + } + + fn visit_enum(self, data: A) -> Result + where + A: EnumAccess<'de>, + { + match try!(data.variant()) { + (Field::Unbounded, v) => v.unit_variant().map(|()| Bound::Unbounded), + (Field::Included, v) => v.newtype_variant().map(Bound::Included), + (Field::Excluded, v) => v.newtype_variant().map(Bound::Excluded), + } + } + } + + const VARIANTS: &'static [&'static str] = &["Unbounded", "Included", "Excluded"]; + + deserializer.deserialize_enum("Bound", VARIANTS, BoundVisitor(PhantomData)) + } +} + +//////////////////////////////////////////////////////////////////////////////// + macro_rules! nonzero_integers { ( $( $T: ident, )+ ) => { $( diff --git a/vendor/serde/src/de/mod.rs b/vendor/serde/src/de/mod.rs index 4ce533450f..896b1a6001 100644 --- a/vendor/serde/src/de/mod.rs +++ b/vendor/serde/src/de/mod.rs @@ -59,13 +59,13 @@ //! - Box\ //! - Box\<\[T\]\> //! - Box\ -//! - Rc\ -//! - Arc\ //! - Cow\<'a, T\> //! - Cell\ //! - RefCell\ //! - Mutex\ //! - RwLock\ +//! - Rc\ *(if* features = ["rc"] *is enabled)* +//! - Arc\ *(if* features = ["rc"] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ @@ -89,6 +89,7 @@ //! - PathBuf //! - Range\ //! - RangeInclusive\ +//! - Bound\ //! - num::NonZero* //! - `!` *(unstable)* //! - **Net types**: @@ -153,7 +154,7 @@ macro_rules! declare_error_trait { /// /// The message should not be capitalized and should not end with a period. /// - /// ```rust + /// ```edition2018 /// # use std::str::FromStr; /// # /// # struct IpAddr; @@ -173,7 +174,7 @@ macro_rules! declare_error_trait { /// where /// D: Deserializer<'de>, /// { - /// let s = try!(String::deserialize(deserializer)); + /// let s = String::deserialize(deserializer)?; /// s.parse().map_err(de::Error::custom) /// } /// } @@ -237,12 +238,16 @@ macro_rules! declare_error_trait { #[cold] fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { if expected.is_empty() { - Error::custom(format_args!("unknown variant `{}`, there are no variants", - variant)) + Error::custom(format_args!( + "unknown variant `{}`, there are no variants", + variant + )) } else { - Error::custom(format_args!("unknown variant `{}`, expected {}", - variant, - OneOf { names: expected })) + Error::custom(format_args!( + "unknown variant `{}`, expected {}", + variant, + OneOf { names: expected } + )) } } @@ -251,12 +256,16 @@ macro_rules! declare_error_trait { #[cold] fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { if expected.is_empty() { - Error::custom(format_args!("unknown field `{}`, there are no fields", - field)) + Error::custom(format_args!( + "unknown field `{}`, there are no fields", + field + )) } else { - Error::custom(format_args!("unknown field `{}`, expected {}", - field, - OneOf { names: expected })) + Error::custom(format_args!( + "unknown field `{}`, expected {}", + field, + OneOf { names: expected } + )) } } @@ -290,7 +299,7 @@ declare_error_trait!(Error: Sized + Debug + Display); /// This is used as an argument to the `invalid_type`, `invalid_value`, and /// `invalid_length` methods of the `Error` trait to build error messages. /// -/// ```rust +/// ```edition2018 /// # use std::fmt; /// # /// # use serde::de::{self, Unexpected, Visitor}; @@ -415,7 +424,7 @@ impl<'a> fmt::Display for Unexpected<'a> { /// Within the context of a `Visitor` implementation, the `Visitor` itself /// (`&self`) is an implementation of this trait. /// -/// ```rust +/// ```edition2018 /// # use std::fmt; /// # /// # use serde::de::{self, Unexpected, Visitor}; @@ -440,7 +449,7 @@ impl<'a> fmt::Display for Unexpected<'a> { /// /// Outside of a `Visitor`, `&"..."` can be used. /// -/// ```rust +/// ```edition2018 /// # use serde::de::{self, Unexpected}; /// # /// # fn example() -> Result<(), E> @@ -561,7 +570,7 @@ pub trait Deserialize<'de>: Sized { /// from the input string, but a `from_reader` function may only deserialize /// owned data. /// -/// ```rust +/// ```edition2018 /// # use serde::de::{Deserialize, DeserializeOwned}; /// # use std::io::{Read, Result}; /// # @@ -600,7 +609,7 @@ impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// /// The canonical API for stateless deserialization looks like this: /// -/// ```rust +/// ```edition2018 /// # use serde::Deserialize; /// # /// # enum Error {} @@ -614,7 +623,7 @@ impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// Adjusting an API like this to support stateful deserialization is a matter /// of accepting a seed as input: /// -/// ```rust +/// ```edition2018 /// # use serde::de::DeserializeSeed; /// # /// # enum Error {} @@ -647,7 +656,7 @@ impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// into it. This requires stateful deserialization using the `DeserializeSeed` /// trait. /// -/// ```rust +/// ```edition2018 /// use std::fmt; /// use std::marker::PhantomData; /// @@ -1137,7 +1146,7 @@ pub trait Deserializer<'de>: Sized { /// human-readable one and binary formats like Bincode will prefer the /// compact one. /// - /// ``` + /// ```edition2018 /// # use std::ops::Add; /// # use std::str::FromStr; /// # @@ -1214,7 +1223,7 @@ pub trait Deserializer<'de>: Sized { /// /// # Example /// -/// ```rust +/// ```edition2018 /// # use std::fmt; /// # /// # use serde::de::{self, Unexpected, Visitor}; @@ -1255,7 +1264,7 @@ pub trait Visitor<'de>: Sized { /// "an integer between 0 and 64". The message should not be capitalized and /// should not end with a period. /// - /// ```rust + /// ```edition2018 /// # use std::fmt; /// # /// # struct S { @@ -1996,7 +2005,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust + /// ```edition2018 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2036,7 +2045,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust + /// ```edition2018 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2092,7 +2101,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust + /// ```edition2018 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2139,7 +2148,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust + /// ```edition2018 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2199,14 +2208,10 @@ pub trait VariantAccess<'de>: Sized { /// /// # Example /// -/// ```rust -/// #[macro_use] -/// extern crate serde_derive; -/// -/// extern crate serde; -/// +/// ```edition2018 /// use std::str::FromStr; -/// use serde::de::{value, Deserialize, IntoDeserializer}; +/// use serde::Deserialize; +/// use serde::de::{value, IntoDeserializer}; /// /// #[derive(Deserialize)] /// enum Setting { @@ -2221,8 +2226,6 @@ pub trait VariantAccess<'de>: Sized { /// Self::deserialize(s.into_deserializer()) /// } /// } -/// # -/// # fn main() {} /// ``` pub trait IntoDeserializer<'de, E: Error = value::Error> { /// The type of the deserializer being converted into. diff --git a/vendor/serde/src/de/value.rs b/vendor/serde/src/de/value.rs index 4f8e2b6ce3..d0a185da2e 100644 --- a/vendor/serde/src/de/value.rs +++ b/vendor/serde/src/de/value.rs @@ -1,14 +1,10 @@ //! Building blocks for deserializing basic values using the `IntoDeserializer` //! trait. //! -//! ```rust -//! #[macro_use] -//! extern crate serde_derive; -//! -//! extern crate serde; -//! +//! ```edition2018 //! use std::str::FromStr; -//! use serde::de::{value, Deserialize, IntoDeserializer}; +//! use serde::Deserialize; +//! use serde::de::{value, IntoDeserializer}; //! //! #[derive(Deserialize)] //! enum Setting { @@ -23,8 +19,6 @@ //! Self::deserialize(s.into_deserializer()) //! } //! } -//! # -//! # fn main() {} //! ``` use lib::*; @@ -1293,10 +1287,40 @@ where visitor.visit_map(self.map) } + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_enum(self) + } + forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any + tuple_struct map struct identifier ignored_any + } +} + +impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer +where + A: de::MapAccess<'de>, +{ + type Error = A::Error; + type Variant = private::MapAsEnum; + + fn variant_seed(mut self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.map.next_key_seed(seed)? { + Some(key) => Ok((key, private::map_as_enum(self.map))), + None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")), + } } } @@ -1305,7 +1329,7 @@ where mod private { use lib::*; - use de::{self, Unexpected}; + use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor}; #[derive(Clone, Debug)] pub struct UnitOnly { @@ -1366,6 +1390,92 @@ mod private { } } + #[derive(Clone, Debug)] + pub struct MapAsEnum { + map: A, + } + + pub fn map_as_enum(map: A) -> MapAsEnum { + MapAsEnum { map: map } + } + + impl<'de, A> VariantAccess<'de> for MapAsEnum + where + A: MapAccess<'de>, + { + type Error = A::Error; + + fn unit_variant(mut self) -> Result<(), Self::Error> { + self.map.next_value() + } + + fn newtype_variant_seed(mut self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + self.map.next_value_seed(seed) + } + + fn tuple_variant(mut self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.map.next_value_seed(SeedTupleVariant { + len: len, + visitor: visitor, + }) + } + + fn struct_variant( + mut self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.map + .next_value_seed(SeedStructVariant { visitor: visitor }) + } + } + + struct SeedTupleVariant { + len: usize, + visitor: V, + } + + impl<'de, V> DeserializeSeed<'de> for SeedTupleVariant + where + V: Visitor<'de>, + { + type Value = V::Value; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_tuple(self.len, self.visitor) + } + } + + struct SeedStructVariant { + visitor: V, + } + + impl<'de, V> DeserializeSeed<'de> for SeedStructVariant + where + V: Visitor<'de>, + { + type Value = V::Value; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_map(self.visitor) + } + } + /// Avoid having to restate the generic types on `MapDeserializer`. The /// `Iterator::Item` contains enough information to figure out K and V. pub trait Pair { diff --git a/vendor/serde/src/export.rs b/vendor/serde/src/export.rs index 805f45abc3..80dcb7f5a3 100644 --- a/vendor/serde/src/export.rs +++ b/vendor/serde/src/export.rs @@ -9,7 +9,7 @@ pub use lib::result::Result::{self, Err, Ok}; pub use self::string::from_utf8_lossy; #[cfg(any(feature = "alloc", feature = "std"))] -pub use lib::Vec; +pub use lib::{ToString, Vec}; mod string { use lib::*; diff --git a/vendor/serde/src/integer128.rs b/vendor/serde/src/integer128.rs index 71db246558..7a24e50ad6 100644 --- a/vendor/serde/src/integer128.rs +++ b/vendor/serde/src/integer128.rs @@ -9,14 +9,12 @@ /// do not need to bother with this macro and may assume support for 128-bit /// integers. /// -/// ```rust -/// #[macro_use] -/// extern crate serde; -/// -/// use serde::Serializer; +/// ```edition2018 /// # use serde::private::ser::Error; /// # /// # struct MySerializer; +/// # +/// use serde::{serde_if_integer128, Serializer}; /// /// impl Serializer for MySerializer { /// type Ok = (); @@ -41,20 +39,18 @@ /// } /// } /// # -/// # __serialize_unimplemented! { +/// # serde::__serialize_unimplemented! { /// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some /// # unit unit_struct unit_variant newtype_struct newtype_variant seq /// # tuple tuple_struct tuple_variant map struct struct_variant /// # } /// } -/// # -/// # fn main() {} /// ``` /// /// When Serde is built with support for 128-bit integers, this macro expands /// transparently into just the input tokens. /// -/// ```rust +/// ```edition2018 /// macro_rules! serde_if_integer128 { /// ($($tt:tt)*) => { /// $($tt)* @@ -65,7 +61,7 @@ /// When built without support for 128-bit integers, this macro expands to /// nothing. /// -/// ```rust +/// ```edition2018 /// macro_rules! serde_if_integer128 { /// ($($tt:tt)*) => {}; /// } diff --git a/vendor/serde/src/lib.rs b/vendor/serde/src/lib.rs index a5b9400f61..4133c1436f 100644 --- a/vendor/serde/src/lib.rs +++ b/vendor/serde/src/lib.rs @@ -46,7 +46,6 @@ //! - [BSON], the data storage and network transfer format used by MongoDB. //! - [Avro], a binary format used within Apache Hadoop, with support for schema //! definition. -//! - [Hjson], a variant of JSON designed to be readable and writable by humans. //! - [JSON5], A superset of JSON including some productions from ES5. //! - [URL], the x-www-form-urlencoded format. //! - [Envy], a way to deserialize environment variables into Rust structs. @@ -64,7 +63,6 @@ //! [RON]: https://github.com/ron-rs/ron //! [BSON]: https://github.com/zonyitoo/bson-rs //! [Avro]: https://github.com/flavray/avro-rs -//! [Hjson]: https://github.com/laktak/hjson-rust //! [JSON5]: https://github.com/callum-oakley/json5-rs //! [URL]: https://github.com/nox/serde_urlencoded //! [Envy]: https://github.com/softprops/envy @@ -75,7 +73,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.82")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.92")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Unstable functionality only if the user asks for it. For tracking and @@ -84,54 +82,38 @@ // https://github.com/serde-rs/serde/issues/812 #![cfg_attr(feature = "unstable", feature(specialization, never_type))] #![cfg_attr(feature = "alloc", feature(alloc))] +#![allow(unknown_lints, bare_trait_objects)] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] -// Whitelisted clippy lints +// Ignored clippy and clippy_pedantic lints #![cfg_attr( feature = "cargo-clippy", allow( - cast_lossless, + // not available in our oldest supported compiler const_static_lifetime, - doc_markdown, - linkedlist, - needless_pass_by_value, + empty_enum, redundant_field_names, + // integer and float ser/de requires these sorts of casts + cast_possible_truncation, + cast_possible_wrap, + cast_precision_loss, + cast_sign_loss, + // things are often more readable this way + cast_lossless, + module_name_repetitions, + single_match_else, type_complexity, - unreadable_literal, - zero_prefixed_literal + use_self, + zero_prefixed_literal, + // not practical + needless_pass_by_value, + similar_names, + // preference + doc_markdown, ) )] -// Whitelisted clippy_pedantic lints -#![cfg_attr(feature = "cargo-clippy", allow( -// integer and float ser/de requires these sorts of casts - cast_possible_truncation, - cast_possible_wrap, - cast_precision_loss, - cast_sign_loss, -// simplifies some macros - invalid_upcast_comparisons, -// things are often more readable this way - decimal_literal_representation, - option_unwrap_used, - result_unwrap_used, - shadow_reuse, - single_match_else, - stutter, - use_self, -// not practical - indexing_slicing, - many_single_char_names, - missing_docs_in_private_items, - similar_names, -// alternative is not stable - empty_enum, - use_debug, -))] -// Blacklisted Rust lints. -// -// Compiler bug involving unused_imports: -// https://github.com/rust-lang/rust/issues/51661 -#![deny(missing_docs, /*unused_imports*/)] +// Rustc lints. +#![deny(missing_docs, unused_imports)] //////////////////////////////////////////////////////////////////////////////// @@ -172,7 +154,7 @@ mod lib { #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::string::{String, ToString}; #[cfg(feature = "std")] - pub use std::string::String; + pub use std::string::{String, ToString}; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::vec::Vec; @@ -219,11 +201,20 @@ mod lib { #[cfg(feature = "std")] pub use std::time::{SystemTime, UNIX_EPOCH}; - #[cfg(any(core_duration, feature = "std"))] - pub use self::core::time::Duration; + #[cfg(all(feature = "std", collections_bound))] + pub use std::collections::Bound; + + #[cfg(core_reverse)] + pub use self::core::cmp::Reverse; + + #[cfg(ops_bound)] + pub use self::core::ops::Bound; #[cfg(range_inclusive)] pub use self::core::ops::RangeInclusive; + + #[cfg(any(core_duration, feature = "std"))] + pub use self::core::time::Duration; } //////////////////////////////////////////////////////////////////////////////// @@ -252,40 +243,6 @@ pub mod private; // Re-export #[derive(Serialize, Deserialize)]. // -// This is a workaround for https://github.com/rust-lang/cargo/issues/1286. -// Without this re-export, crates that put Serde derives behind a cfg_attr would -// need to use some silly feature name that depends on both serde and -// serde_derive. -// -// [features] -// serde-impls = ["serde", "serde_derive"] -// -// [dependencies] -// serde = { version = "1.0", optional = true } -// serde_derive = { version = "1.0", optional = true } -// -// # Used like this: -// # #[cfg(feature = "serde-impls")] -// # #[macro_use] -// # extern crate serde_derive; -// # -// # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))] -// # struct S { /* ... */ } -// -// The re-exported derives allow crates to use "serde" as the name of their -// Serde feature which is more intuitive. -// -// [dependencies] -// serde = { version = "1.0", optional = true, features = ["derive"] } -// -// # Used like this: -// # #[cfg(feature = "serde")] -// # #[macro_use] -// # extern crate serde; -// # -// # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -// # struct S { /* ... */ } -// // The reason re-exporting is not enabled by default is that disabling it would // be annoying for crates that provide handwritten impls or data formats. They // would need to disable default features and then explicitly re-enable std. diff --git a/vendor/serde/src/macros.rs b/vendor/serde/src/macros.rs index a10280da90..57600a5351 100644 --- a/vendor/serde/src/macros.rs +++ b/vendor/serde/src/macros.rs @@ -11,10 +11,8 @@ /// input. This requires repetitive implementations of all the [`Deserializer`] /// trait methods. /// -/// ```rust -/// # #[macro_use] -/// # extern crate serde; -/// # +/// ```edition2018 +/// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # /// # struct MyDeserializer; @@ -43,18 +41,14 @@ /// # tuple_struct map struct enum identifier ignored_any /// # } /// # } -/// # -/// # fn main() {} /// ``` /// /// The `forward_to_deserialize_any!` macro implements these simple forwarding /// methods so that they forward directly to [`Deserializer::deserialize_any`]. /// You can choose which methods to forward. /// -/// ```rust -/// # #[macro_use] -/// # extern crate serde; -/// # +/// ```edition2018 +/// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # /// # struct MyDeserializer; @@ -77,8 +71,6 @@ /// tuple_struct map struct enum identifier ignored_any /// } /// } -/// # -/// # fn main() {} /// ``` /// /// The macro assumes the convention that your `Deserializer` lifetime parameter @@ -86,12 +78,10 @@ /// called `V`. A different type parameter and a different lifetime can be /// specified explicitly if necessary. /// -/// ```rust -/// # #[macro_use] -/// # extern crate serde; -/// # +/// ```edition2018 /// # use std::marker::PhantomData; /// # +/// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # /// # struct MyDeserializer(PhantomData); @@ -113,8 +103,6 @@ /// tuple_struct map struct enum identifier ignored_any /// } /// # } -/// # -/// # fn main() {} /// ``` /// /// [`Deserializer`]: trait.Deserializer.html diff --git a/vendor/serde/src/private/de.rs b/vendor/serde/src/private/de.rs index 18335d003c..feb3d4c7bf 100644 --- a/vendor/serde/src/private/de.rs +++ b/vendor/serde/src/private/de.rs @@ -2709,7 +2709,7 @@ where } Err(Error::custom(format_args!( - "no variant of enum {} not found in flattened data", + "no variant of enum {} found in flattened data", name ))) } diff --git a/vendor/serde/src/ser/impls.rs b/vendor/serde/src/ser/impls.rs index 3fab473d2c..49b7477a4f 100644 --- a/vendor/serde/src/ser/impls.rs +++ b/vendor/serde/src/ser/impls.rs @@ -160,10 +160,12 @@ macro_rules! array_impls { } } -array_impls!(01 02 03 04 05 06 07 08 09 10 - 11 12 13 14 15 16 17 18 19 20 - 21 22 23 24 25 26 27 28 29 30 - 31 32); +array_impls! { + 01 02 03 04 05 06 07 08 09 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32 +} //////////////////////////////////////////////////////////////////////////////// @@ -256,6 +258,29 @@ where //////////////////////////////////////////////////////////////////////////////// +#[cfg(any(ops_bound, collections_bound))] +impl Serialize for Bound +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + Bound::Unbounded => serializer.serialize_unit_variant("Bound", 0, "Unbounded"), + Bound::Included(ref value) => { + serializer.serialize_newtype_variant("Bound", 1, "Included", value) + } + Bound::Excluded(ref value) => { + serializer.serialize_newtype_variant("Bound", 2, "Excluded", value) + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////// + impl Serialize for () { #[inline] fn serialize(&self, serializer: S) -> Result @@ -799,3 +824,17 @@ where self.0.serialize(serializer) } } + +#[cfg(core_reverse)] +impl Serialize for Reverse +where + T: Serialize, +{ + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} diff --git a/vendor/serde/src/ser/impossible.rs b/vendor/serde/src/ser/impossible.rs index 674d748457..90bab29a07 100644 --- a/vendor/serde/src/ser/impossible.rs +++ b/vendor/serde/src/ser/impossible.rs @@ -15,10 +15,7 @@ use ser::{ /// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`], /// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`]. /// -/// ```rust -/// # #[macro_use] -/// # extern crate serde; -/// # +/// ```edition2018 /// # use serde::ser::{Serializer, Impossible}; /// # use serde::private::ser::Error; /// # @@ -44,14 +41,12 @@ use ser::{ /// } /// /// /* other Serializer methods */ -/// # __serialize_unimplemented! { +/// # serde::__serialize_unimplemented! { /// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some /// # unit unit_struct unit_variant newtype_struct newtype_variant /// # tuple tuple_struct tuple_variant map struct struct_variant /// # } /// } -/// # -/// # fn main() {} /// ``` /// /// [`Serializer`]: trait.Serializer.html diff --git a/vendor/serde/src/ser/mod.rs b/vendor/serde/src/ser/mod.rs index 5773245059..318b3799a2 100644 --- a/vendor/serde/src/ser/mod.rs +++ b/vendor/serde/src/ser/mod.rs @@ -56,13 +56,13 @@ //! - PhantomData\ //! - **Wrapper types**: //! - Box\ -//! - Rc\ -//! - Arc\ //! - Cow\<'a, T\> //! - Cell\ //! - RefCell\ //! - Mutex\ //! - RwLock\ +//! - Rc\ *(if* features = ["rc"] *is enabled)* +//! - Arc\ *(if* features = ["rc"] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ @@ -84,6 +84,7 @@ //! - PathBuf //! - Range\ //! - RangeInclusive\ +//! - Bound\ //! - num::NonZero* //! - `!` *(unstable)* //! - **Net types**: @@ -137,7 +138,7 @@ macro_rules! declare_error_trait { /// For example, a filesystem [`Path`] may refuse to serialize /// itself if it contains invalid UTF-8 data. /// - /// ```rust + /// ```edition2018 /// # struct Path; /// # /// # impl Path { @@ -210,7 +211,7 @@ pub trait Serialize { /// See the [Implementing `Serialize`] section of the manual for more /// information about how to implement this method. /// - /// ```rust + /// ```edition2018 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Person { @@ -377,13 +378,10 @@ pub trait Serializer: Sized { /// Serialize a `bool` value. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for bool { /// fn serialize(&self, serializer: S) -> Result @@ -393,8 +391,6 @@ pub trait Serializer: Sized { /// serializer.serialize_bool(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_bool(self, v: bool) -> Result; @@ -404,13 +400,10 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for i8 { /// fn serialize(&self, serializer: S) -> Result @@ -420,8 +413,6 @@ pub trait Serializer: Sized { /// serializer.serialize_i8(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_i8(self, v: i8) -> Result; @@ -431,13 +422,10 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for i16 { /// fn serialize(&self, serializer: S) -> Result @@ -447,8 +435,6 @@ pub trait Serializer: Sized { /// serializer.serialize_i16(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_i16(self, v: i16) -> Result; @@ -458,13 +444,10 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for i32 { /// fn serialize(&self, serializer: S) -> Result @@ -474,20 +457,15 @@ pub trait Serializer: Sized { /// serializer.serialize_i32(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_i32(self, v: i32) -> Result; /// Serialize an `i64` value. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for i64 { /// fn serialize(&self, serializer: S) -> Result @@ -497,21 +475,16 @@ pub trait Serializer: Sized { /// serializer.serialize_i64(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_i64(self, v: i64) -> Result; serde_if_integer128! { /// Serialize an `i128` value. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for i128 { /// fn serialize(&self, serializer: S) -> Result @@ -521,8 +494,6 @@ pub trait Serializer: Sized { /// serializer.serialize_i128(*self) /// } /// } - /// # - /// # fn main() {} /// ``` /// /// This method is available only on Rust compiler versions >=1.26. The @@ -539,13 +510,10 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for u8 { /// fn serialize(&self, serializer: S) -> Result @@ -555,8 +523,6 @@ pub trait Serializer: Sized { /// serializer.serialize_u8(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_u8(self, v: u8) -> Result; @@ -566,13 +532,10 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for u16 { /// fn serialize(&self, serializer: S) -> Result @@ -582,8 +545,6 @@ pub trait Serializer: Sized { /// serializer.serialize_u16(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_u16(self, v: u16) -> Result; @@ -593,13 +554,10 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for u32 { /// fn serialize(&self, serializer: S) -> Result @@ -609,20 +567,15 @@ pub trait Serializer: Sized { /// serializer.serialize_u32(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_u32(self, v: u32) -> Result; /// Serialize a `u64` value. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for u64 { /// fn serialize(&self, serializer: S) -> Result @@ -632,21 +585,16 @@ pub trait Serializer: Sized { /// serializer.serialize_u64(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_u64(self, v: u64) -> Result; serde_if_integer128! { /// Serialize a `u128` value. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for u128 { /// fn serialize(&self, serializer: S) -> Result @@ -656,8 +604,6 @@ pub trait Serializer: Sized { /// serializer.serialize_u128(*self) /// } /// } - /// # - /// # fn main() {} /// ``` /// /// This method is available only on Rust compiler versions >=1.26. The @@ -674,13 +620,10 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `f64` and /// forward to `serialize_f64`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for f32 { /// fn serialize(&self, serializer: S) -> Result @@ -690,20 +633,15 @@ pub trait Serializer: Sized { /// serializer.serialize_f32(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_f32(self, v: f32) -> Result; /// Serialize an `f64` value. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for f64 { /// fn serialize(&self, serializer: S) -> Result @@ -713,8 +651,6 @@ pub trait Serializer: Sized { /// serializer.serialize_f64(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_f64(self, v: f64) -> Result; @@ -723,13 +659,10 @@ pub trait Serializer: Sized { /// If the format does not support characters, it is reasonable to serialize /// it as a single element `str` or a `u32`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for char { /// fn serialize(&self, serializer: S) -> Result @@ -739,20 +672,15 @@ pub trait Serializer: Sized { /// serializer.serialize_char(*self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_char(self, v: char) -> Result; /// Serialize a `&str`. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for str { /// fn serialize(&self, serializer: S) -> Result @@ -762,8 +690,6 @@ pub trait Serializer: Sized { /// serializer.serialize_str(self) /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_str(self, v: &str) -> Result; @@ -775,10 +701,7 @@ pub trait Serializer: Sized { /// `serialize_seq`. If forwarded, the implementation looks usually just /// like this: /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::ser::{Serializer, SerializeSeq}; /// # use serde::private::ser::Error; /// # @@ -796,22 +719,18 @@ pub trait Serializer: Sized { /// seq.end() /// } /// # - /// # __serialize_unimplemented! { + /// # serde::__serialize_unimplemented! { /// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str none some /// # unit unit_struct unit_variant newtype_struct newtype_variant /// # seq tuple tuple_struct tuple_variant map struct struct_variant /// # } /// # } - /// # - /// # fn main() {} /// ``` fn serialize_bytes(self, v: &[u8]) -> Result; /// Serialize a [`None`] value. /// - /// ```rust - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::{Serialize, Serializer}; /// # /// # enum Option { @@ -819,7 +738,7 @@ pub trait Serializer: Sized { /// # None, /// # } /// # - /// # use Option::{Some, None}; + /// # use self::Option::{Some, None}; /// # /// impl Serialize for Option /// where @@ -844,9 +763,7 @@ pub trait Serializer: Sized { /// Serialize a [`Some(T)`] value. /// - /// ```rust - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::{Serialize, Serializer}; /// # /// # enum Option { @@ -854,7 +771,7 @@ pub trait Serializer: Sized { /// # None, /// # } /// # - /// # use Option::{Some, None}; + /// # use self::Option::{Some, None}; /// # /// impl Serialize for Option /// where @@ -881,13 +798,10 @@ pub trait Serializer: Sized { /// Serialize a `()` value. /// - /// ```rust - /// # #[macro_use] - /// # extern crate serde; - /// # + /// ```edition2018 /// # use serde::Serializer; /// # - /// # __private_serialize!(); + /// # serde::__private_serialize!(); /// # /// impl Serialize for () { /// fn serialize(&self, serializer: S) -> Result @@ -897,8 +811,6 @@ pub trait Serializer: Sized { /// serializer.serialize_unit() /// } /// } - /// # - /// # fn main() {} /// ``` fn serialize_unit(self) -> Result; @@ -906,7 +818,7 @@ pub trait Serializer: Sized { /// /// A reasonable implementation would be to forward to `serialize_unit`. /// - /// ```rust + /// ```edition2018 /// use serde::{Serialize, Serializer}; /// /// struct Nothing; @@ -928,7 +840,7 @@ pub trait Serializer: Sized { /// this variant within the enum, and the `variant` is the name of the /// variant. /// - /// ```rust + /// ```edition2018 /// use serde::{Serialize, Serializer}; /// /// enum E { @@ -961,7 +873,7 @@ pub trait Serializer: Sized { /// wrappers around the data they contain. A reasonable implementation would /// be to forward to `value.serialize(self)`. /// - /// ```rust + /// ```edition2018 /// use serde::{Serialize, Serializer}; /// /// struct Millimeters(u8); @@ -989,7 +901,7 @@ pub trait Serializer: Sized { /// this variant within the enum, and the `variant` is the name of the /// variant. The `value` is the data contained within this newtype variant. /// - /// ```rust + /// ```edition2018 /// use serde::{Serialize, Serializer}; /// /// enum E { @@ -1027,7 +939,7 @@ pub trait Serializer: Sized { /// not be computable before the sequence is iterated. Some serializers only /// support sequences whose length is known up front. /// - /// ```rust + /// ```edition2018 /// # use std::marker::PhantomData; /// # /// # struct Vec(PhantomData); @@ -1072,7 +984,7 @@ pub trait Serializer: Sized { /// This call must be followed by zero or more calls to `serialize_element`, /// then a call to `end`. /// - /// ```rust + /// ```edition2018 /// use serde::ser::{Serialize, Serializer, SerializeTuple}; /// /// # mod fool { @@ -1102,7 +1014,7 @@ pub trait Serializer: Sized { /// } /// ``` /// - /// ```rust + /// ```edition2018 /// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// const VRAM_SIZE: usize = 386; @@ -1130,7 +1042,7 @@ pub trait Serializer: Sized { /// The `name` is the name of the tuple struct and the `len` is the number /// of data fields that will be serialized. /// - /// ```rust + /// ```edition2018 /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// /// struct Rgb(u8, u8, u8); @@ -1162,7 +1074,7 @@ pub trait Serializer: Sized { /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// - /// ```rust + /// ```edition2018 /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// /// enum E { @@ -1208,7 +1120,7 @@ pub trait Serializer: Sized { /// be computable before the map is iterated. Some serializers only support /// maps whose length is known up front. /// - /// ```rust + /// ```edition2018 /// # use std::marker::PhantomData; /// # /// # struct HashMap(PhantomData, PhantomData); @@ -1256,7 +1168,7 @@ pub trait Serializer: Sized { /// The `name` is the name of the struct and the `len` is the number of /// data fields that will be serialized. /// - /// ```rust + /// ```edition2018 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Rgb { @@ -1292,7 +1204,7 @@ pub trait Serializer: Sized { /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// - /// ```rust + /// ```edition2018 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// /// enum E { @@ -1334,7 +1246,7 @@ pub trait Serializer: Sized { /// using [`serialize_seq`]. Implementors should not need to override this /// method. /// - /// ```rust + /// ```edition2018 /// use serde::{Serialize, Serializer}; /// /// struct SecretlyOneHigher { @@ -1371,7 +1283,7 @@ pub trait Serializer: Sized { /// using [`serialize_map`]. Implementors should not need to override this /// method. /// - /// ```rust + /// ```edition2018 /// use serde::{Serialize, Serializer}; /// use std::collections::BTreeSet; /// @@ -1411,7 +1323,7 @@ pub trait Serializer: Sized { /// delegates to [`serialize_str`]. Serializers are encouraged to provide a /// more efficient implementation if possible. /// - /// ```rust + /// ```edition2018 /// # struct DateTime; /// # /// # impl DateTime { @@ -1452,7 +1364,7 @@ pub trait Serializer: Sized { /// of this method. If no more sensible behavior is possible, the /// implementation is expected to return an error. /// - /// ```rust + /// ```edition2018 /// # struct DateTime; /// # /// # impl DateTime { @@ -1487,7 +1399,7 @@ pub trait Serializer: Sized { /// human-readable one and binary formats like Bincode will prefer the /// compact one. /// - /// ``` + /// ```edition2018 /// # use std::fmt::{self, Display}; /// # /// # struct Timestamp; @@ -1536,7 +1448,7 @@ pub trait Serializer: Sized { /// /// # Example use /// -/// ```rust +/// ```edition2018 /// # use std::marker::PhantomData; /// # /// # struct Vec(PhantomData); @@ -1600,7 +1512,7 @@ pub trait SerializeSeq { /// /// # Example use /// -/// ```rust +/// ```edition2018 /// use serde::ser::{Serialize, Serializer, SerializeTuple}; /// /// # mod fool { @@ -1630,7 +1542,7 @@ pub trait SerializeSeq { /// } /// ``` /// -/// ```rust +/// ```edition2018 /// # use std::marker::PhantomData; /// # /// # struct Array(PhantomData); @@ -1700,7 +1612,7 @@ pub trait SerializeTuple { /// /// # Example use /// -/// ```rust +/// ```edition2018 /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// /// struct Rgb(u8, u8, u8); @@ -1745,7 +1657,7 @@ pub trait SerializeTupleStruct { /// /// # Example use /// -/// ```rust +/// ```edition2018 /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// /// enum E { @@ -1803,7 +1715,7 @@ pub trait SerializeTupleVariant { /// /// # Example use /// -/// ```rust +/// ```edition2018 /// # use std::marker::PhantomData; /// # /// # struct HashMap(PhantomData, PhantomData); @@ -1914,7 +1826,7 @@ pub trait SerializeMap { /// /// # Example use /// -/// ```rust +/// ```edition2018 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Rgb { @@ -1974,7 +1886,7 @@ pub trait SerializeStruct { /// /// # Example use /// -/// ```rust +/// ```edition2018 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// /// enum E { diff --git a/vendor/smallvec/.cargo-checksum.json b/vendor/smallvec/.cargo-checksum.json index 6aceff153a..57d87f2e00 100644 --- a/vendor/smallvec/.cargo-checksum.json +++ b/vendor/smallvec/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"c629cca1fcb7a0d38137460d8874e840031a9da327ab6d79d00696a326400678","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"38eef4ebde6fe6effa12a2dbca3bd69d6446b2935f19a329ac4926f1cb2e5013","benches/bench.rs":"9dca7122a3dcb2c099e49807e4d3b8f01d9220e2b3db0a54e9901ee74392866f","lib.rs":"0da9a979eb6cdf81e6dd58a6742613d08a8e0f5003a01665036aceeb10fa34f0"},"package":"b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"} \ No newline at end of file +{"files":{"Cargo.toml":"a064123fc22a52158c37be025c3b70d413c4b1ee743e92a2e80ed419e2992d65","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"38eef4ebde6fe6effa12a2dbca3bd69d6446b2935f19a329ac4926f1cb2e5013","benches/bench.rs":"9dca7122a3dcb2c099e49807e4d3b8f01d9220e2b3db0a54e9901ee74392866f","lib.rs":"4d6998b0b80a85e85cf00bd317a88518067e9e8ba191185418263dec67069c16"},"package":"ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"} \ No newline at end of file diff --git a/vendor/smallvec/Cargo.toml b/vendor/smallvec/Cargo.toml index dd07def0a1..5b23e5a16b 100644 --- a/vendor/smallvec/Cargo.toml +++ b/vendor/smallvec/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "smallvec" -version = "0.6.7" +version = "0.6.10" authors = ["Simon Sapin "] description = "'Small vector' optimization: store up to a small number of items on the stack" documentation = "https://doc.servo.org/smallvec/" @@ -28,9 +28,6 @@ path = "lib.rs" [dependencies.serde] version = "1" optional = true - -[dependencies.unreachable] -version = "1.0.0" [dev-dependencies.bincode] version = "1.0.1" diff --git a/vendor/smallvec/lib.rs b/vendor/smallvec/lib.rs index 74c4abf721..e45ca7aebd 100644 --- a/vendor/smallvec/lib.rs +++ b/vendor/smallvec/lib.rs @@ -46,9 +46,6 @@ use alloc::vec::Vec; #[cfg(feature = "serde")] extern crate serde; -extern crate unreachable; -use unreachable::UncheckedOptionExt; - #[cfg(not(feature = "std"))] mod std { pub use core::*; @@ -60,7 +57,6 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::{IntoIterator, FromIterator, repeat}; use std::mem; -#[cfg(not(feature = "union"))] use std::mem::ManuallyDrop; use std::ops; use std::ptr; @@ -132,13 +128,24 @@ macro_rules! smallvec { }); } +/// Hint to the optimizer that any code path which calls this function is +/// statically unreachable and can be removed. +/// +/// Equivalent to `std::hint::unreachable_unchecked` but works in older versions of Rust. +#[inline] +pub unsafe fn unreachable() -> ! { + enum Void {} + let x: &Void = mem::transmute(1usize); + match *x {} +} + /// `panic!()` in debug builds, optimization hint in release. #[cfg(not(feature = "union"))] macro_rules! debug_unreachable { () => { debug_unreachable!("entered unreachable code") }; ($e:expr) => { if cfg!(not(debug_assertions)) { - unreachable::unreachable(); + unreachable(); } else { panic!($e); } @@ -268,9 +275,8 @@ impl<'a, T: 'a> Drop for Drain<'a,T> { } #[cfg(feature = "union")] -#[allow(unions_with_drop_fields)] union SmallVecData { - inline: A, + inline: ManuallyDrop, heap: (*mut A::Item, usize), } @@ -286,10 +292,10 @@ impl SmallVecData { } #[inline] fn from_inline(inline: A) -> SmallVecData { - SmallVecData { inline } + SmallVecData { inline: ManuallyDrop::new(inline) } } #[inline] - unsafe fn into_inline(self) -> A { self.inline } + unsafe fn into_inline(self) -> A { ManuallyDrop::into_inner(self.inline) } #[inline] unsafe fn heap(&self) -> (*mut A::Item, usize) { self.heap @@ -363,7 +369,7 @@ unsafe impl Sync for SmallVecData {} /// A `Vec`-like container that can store a small number of elements inline. /// /// `SmallVec` acts like a vector, but can store a limited amount of data inline within the -/// `Smallvec` struct rather than in a separate allocation. If the data exceeds this limit, the +/// `SmallVec` struct rather than in a separate allocation. If the data exceeds this limit, the /// `SmallVec` will "spill" its data onto the heap, allocating a new buffer to hold it. /// /// The amount of data that a `SmallVec` can store inline depends on its backing store. The backing @@ -648,6 +654,7 @@ impl SmallVec { } self.data = SmallVecData::from_inline(mem::uninitialized()); ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len); + self.capacity = len; } else if new_cap != cap { let mut vec = Vec::with_capacity(new_cap); let new_alloc = vec.as_mut_ptr(); @@ -658,6 +665,8 @@ impl SmallVec { if unspilled { return; } + } else { + return; } deallocate(ptr, cap); } @@ -760,7 +769,7 @@ impl SmallVec { pub fn swap_remove(&mut self, index: usize) -> A::Item { let len = self.len(); self.swap(len - 1, index); - unsafe { self.pop().unchecked_unwrap() } + self.pop().unwrap_or_else(|| unsafe { unreachable() }) } /// Remove all elements from the vector. @@ -1342,18 +1351,16 @@ impl Extend for SmallVec { self.reserve(lower_size_bound); unsafe { - let len = self.len(); - let ptr = self.as_mut_ptr().offset(len as isize); - let mut count = 0; - while count < lower_size_bound { + let (ptr, len_ptr, cap) = self.triple_mut(); + let mut len = SetLenOnDrop::new(len_ptr); + while len.get() < cap { if let Some(out) = iter.next() { - ptr::write(ptr.offset(count as isize), out); - count += 1; + ptr::write(ptr.offset(len.get() as isize), out); + len.increment_len(1); } else { - break; + return; } } - self.set_len(len + count); } for elem in iter { @@ -1562,6 +1569,11 @@ impl<'a> SetLenOnDrop<'a> { SetLenOnDrop { local_len: *len, len: len } } + #[inline] + fn get(&self) -> usize { + self.local_len + } + #[inline] fn increment_len(&mut self, increment: usize) { self.local_len += increment; @@ -2302,4 +2314,47 @@ mod tests { let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap(); assert_eq!(small_vec, decoded); } + + #[test] + fn grow_to_shrink() { + let mut v: SmallVec<[u8; 2]> = SmallVec::new(); + v.push(1); + v.push(2); + v.push(3); + assert!(v.spilled()); + v.clear(); + // Shrink to inline. + v.grow(2); + assert!(!v.spilled()); + assert_eq!(v.capacity(), 2); + assert_eq!(v.len(), 0); + v.push(4); + assert_eq!(v[..], [4]); + } + + #[test] + fn resumable_extend() { + let s = "a b c"; + // This iterator yields: (Some('a'), None, Some('b'), None, Some('c')), None + let it = s + .chars() + .scan(0, |_, ch| if ch.is_whitespace() { None } else { Some(ch) }); + let mut v: SmallVec<[char; 4]> = SmallVec::new(); + v.extend(it); + assert_eq!(v[..], ['a']); + } + + #[test] + fn grow_spilled_same_size() { + let mut v: SmallVec<[u8; 2]> = SmallVec::new(); + v.push(0); + v.push(1); + v.push(2); + assert!(v.spilled()); + assert_eq!(v.capacity(), 4); + // grow with the same capacity + v.grow(4); + assert_eq!(v.capacity(), 4); + assert_eq!(v[..], [0, 1, 2]); + } } diff --git a/vendor/syn/.cargo-checksum.json b/vendor/syn/.cargo-checksum.json index f7bec3d477..c4292aa620 100644 --- a/vendor/syn/.cargo-checksum.json +++ b/vendor/syn/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"64bc79612a946e09337a2e489eb47319a1b8c5612065f9a115fd63adebda912e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"f033c371492a4769d377a8bf1a139adc7bf94ea00595b867a3e234eeab994c8c","README.md":"2aea43e1219e72c10347981dc5fb4969b1ec711fb6fb97771d80e0644dc3d334","src/attr.rs":"492a940c41fec7f5bf91b5bc5287e698afd165f25f996804d52e5b1d6439bc41","src/buffer.rs":"a82b47bb12ec0de4159a7677712db5f4f54c145eb61aa88a1696d32cf143d50e","src/data.rs":"c34df5d623fed7a52be01fc625a4502f6ad97dc8feb25c51f7d57029dbdd91dd","src/derive.rs":"7a2246e8ee03fcbea040363d0b943daac696667ba799218231307c1b7a96aeed","src/error.rs":"097c69bc51135a6f6d832e7e008130242f4f5ddf934e8209b7a72f42f2fab5bf","src/export.rs":"1f7e017dac9426e91c796445e733c390c408c808ba9c21cb7df7799b67352fde","src/expr.rs":"4a78ff8249fcda2636f3ef63459c1731eefc9301b35785641c6cbbedd2cc34c3","src/ext.rs":"d86df834f299e16a8e6afbfe62588ecfd18144ad010ba6b579c44e0dc3fb6415","src/file.rs":"ebd350b5ff548cdbb21a0fadd5572575a216a1b0caef36dd46477ca324c7af6f","src/gen/fold.rs":"7f7ab907e3c17b503a72707e2f8d9fc29d9139269d810ea9b6511af9de7d3080","src/gen/visit.rs":"0a4543ac9f82d8ab7ccf02c55e8325ff9b859e36ea08d3e187a4836f470eef1c","src/gen/visit_mut.rs":"66441522f544056cd464740e8ba614688a5f417857c649550eeba2b589ef6096","src/gen_helper.rs":"d128fbd24fadfc5634976bdb9188c649f9905718c9c987a2839c3e6134b155a2","src/generics.rs":"929eaacd293b86389d4b05e03bc1a1cd093ae3925c8d316da4a0c57c8e4f6252","src/group.rs":"e1b4336e9cd8f01c139bdb9cd4b3445f37c84f4e2cc64c6503e520eaea8dc937","src/ident.rs":"61534c48949ebfa03e948874ef64174e1c8111c3b953edd58f79748fe9e00507","src/item.rs":"3470593477d41eebeb4ff0f674d2dade7dfb91ff3ebc57e8a62342a88e989176","src/keyword.rs":"7fbb01d0aa94a41a5bb1f23e61af1ba0de828d62df4f9356fc012dc7ecced077","src/lib.rs":"3ebc963bba225f8d8128608894c15686f103c5ef349c087d5260ee8ab63d8c2b","src/lifetime.rs":"3174a81cea3eef0ec1555900b96b1641d6d3ed3609bc17d72b02a1495377ac35","src/lit.rs":"a3dee9d747a84cc153b01a553eb371533e9c555f58ad92b43315a30f4e4c1ed2","src/lookahead.rs":"386fea0113a3fbfcad77183e9c3329a784b81832a3781a482c647fc1e84df059","src/mac.rs":"8a7efbdc9498612844c88660312117c401685bf300da7e91bef7effde3026019","src/macros.rs":"518e7943bc5565b9beea75df6a3602c698ee9cb096baf79a36b34f753b97615f","src/op.rs":"83bbe2199946abbf1d4a0bc6eb0d97285439f77e8e02646b8e3b707485e4301e","src/parse.rs":"2096d114bb7c9aa1b4d1a8c89f9757017af5d07c9f5b315d1f61ee13acc32266","src/parse_macro_input.rs":"b47282bc85d7da7941f6abecbe09f7bf0bb908b66dde793b00b5df7e97c2c7ed","src/parse_quote.rs":"afbaa9c2af3d20990847add9436111db0e62550261ec1004d970825a31c569ac","src/path.rs":"e76c651b1e59c9203d310f157047023283e387ef42639ab3db38d89eb22e714d","src/print.rs":"7ebb68123898f2ebbae12abf028747c05bea7b08f1e96b17164f1dcebdab7355","src/punctuated.rs":"01539dcb51c75e0fe0a4cdfb7716a909ce1bfd0767370c04043159a0a0dec154","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"c5350463b3ab69cd49ef7afa2688ba3f5e24fc02ef26bf9587afaf3dc60415dd","src/synom.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/thread.rs":"798dd0a6cca7807f1d55c1f79cec967314a75c4e8e2cfdb5644499c22618b307","src/token.rs":"14d0311fafbca854eaffd7966171db5e97d8b594994ca30f7e4ba357f3d6ea7b","src/tt.rs":"1272339be3d2ba64c025cba8d08cff7bb7b61770fc6e5da641db4d56c162e066","src/ty.rs":"baf7464aa3b5b0be061c808605352346086a6507a6e84ee9970a5bcb0d02114e"},"package":"ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"} \ No newline at end of file +{"files":{"Cargo.toml":"ab290a61eab96bcb24386463eec252a4c49c3913c4460207ae5750038dd25c64","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"dce3b1d25e72ea36e3d926a39a2bbab0bc88c84b6f60396d80fc4a4f53f4f915","build.rs":"17c8493aed4032c8cd0d2f2ab8929b7e49e8e2664953658ba3d96a54324902ce","src/attr.rs":"2eb9cf2f094f861fff0ae339e378f6aea8683d2dcfad99700d5287989f458378","src/buffer.rs":"fac77febe022ab4982078c73ca502f9d698a402b3eca0f8e9c7a2796af01e5f4","src/custom_keyword.rs":"f68d4b9c0aa97a481154d4df763099c2ad81fd1993111543ecfc59d766f3044f","src/custom_punctuation.rs":"f1944db8df2d2958ebf285eee3ec5ecdfcd4802e827e08ebf6f1873bb10a0fa7","src/data.rs":"54ee54c3c650bc5e200d4bea947d6e89093a39f2444cd43e8861f5852975e0bc","src/derive.rs":"eb041b47a73bace73c2872cd9a8e190de7e2b3b57cd57213770f088ec19ab3c6","src/error.rs":"aac440c1d58549036343be2cc844d5322aafd917db58bc882d5a48efc5864a23","src/export.rs":"1f7e017dac9426e91c796445e733c390c408c808ba9c21cb7df7799b67352fde","src/expr.rs":"ebd3f4222064412f5e714cc649a70796a75cf07faf56ebe6d1d1ddb702aa9381","src/ext.rs":"49d40f09ad2d2748bc3d1a200026886d1c5997000c3b027bdd066605689e15e5","src/file.rs":"abb9f5e71a8a6b52649c15da21d3f99e25a727d87c2f87d2744ac3970c1d683f","src/gen/fold.rs":"dff8b585e14451b258a171a771c78ba2ba28d323212fdb40dc0d6bf0c4e684b6","src/gen/visit.rs":"b6131f70677f9cc19deb8f225f98f1dbdf00f75b0d917009af0bbaddade9fe4f","src/gen/visit_mut.rs":"6dd24eeb7e294dcf0daad0e60a961a2f89c562fc29f4e28357e68ecc32526fe3","src/gen_helper.rs":"644b1d31987919c0239891d8f90c09f3bf541a71fb85e744438e4814cc6dff89","src/generics.rs":"51391891595b6bc56ba6c94aabf7c3bb4e8a7d8d76d9835f7e4e6ec101c01c19","src/group.rs":"03487f75d0abd302f06e50eb09d14ab83fb60c67e1f2602be53ca3f28a833b90","src/ident.rs":"d90794ecc45dbb25727a7889040ba644b588ca2b0b7f497a726e836c6b762a20","src/item.rs":"7131761b314ec4aaf0de11ff58c1f73cdcfd089c2771add2ccdbc06c623cba4b","src/keyword.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/lib.rs":"ed5358414e4c48f6e43863f1f4d91be111123696e9c4c1cd159ba0463b67068e","src/lifetime.rs":"7912a4c77ee805e912fb28c7f434836ea82540263d549877cd5edfbe32d1bf95","src/lit.rs":"bc034e4443a32f2066b41f62e05946143f60397fbbd05016c0020c4818e0a0f8","src/lookahead.rs":"5a6a4adf75c442ec9a312e64ee9dca75da4772e774a7f095bdb2f91fc790178e","src/mac.rs":"a91623ed9c1de7b18ef752db79a242002e95156497a52a1790a75069915d22ee","src/macros.rs":"2f91e07a1aec4b385986c0a0f66274e8de1c1aa81f95d398a5cd364b3c451bb4","src/op.rs":"01edb1e07b6d60b266797ca4b30788b0a511452228e04073a11f0b61f106a0e7","src/parse.rs":"f9250de07bc32e8278a3063bb705018d32994787f9afc697bcfa9e97ce4d5fb5","src/parse_macro_input.rs":"8df7b4c1b361171f3fefb0490dec570ad29c024c04e35184b296725f97f2002c","src/parse_quote.rs":"d5784e14e0b2954077ce4fe4628af8e7bf9176b74dc0b2c2627abb26c5ac9fc1","src/path.rs":"28c4e198009849fb663cc223e97265d9fab10864f70111466e53c3da8964ca00","src/print.rs":"7ebb68123898f2ebbae12abf028747c05bea7b08f1e96b17164f1dcebdab7355","src/punctuated.rs":"ccfd763c273fd1e6b6a7a551669e8aad47da6d13f700a53ad55b9f58f2f396da","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"83b4ab1e2138ac9340eaa8234ad1d9f7468b450ddf3a852e574cac18e4f766b8","src/thread.rs":"ac3f4aa972b0dee5b9ae5202c5cd6bef46823fc91ff83787a3fe1bdfb8f79135","src/token.rs":"5009af54aff85a5019c8532b63cc3e9419d00fb85ac6849d86fd8cb1e4dcd78d","src/tt.rs":"b3d99cbd68cd50749f26f4afa138e6366d327099ed566b30c315ccb58fa26ded","src/ty.rs":"52cea4f3b094d36f3be7f94c63f1eff1add168d036fce8a0dcacfb6ab5c54926"},"package":"641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3"} \ No newline at end of file diff --git a/vendor/syn/Cargo.toml b/vendor/syn/Cargo.toml index 2c36474ae5..be7d9c86e1 100644 --- a/vendor/syn/Cargo.toml +++ b/vendor/syn/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,28 +12,20 @@ [package] name = "syn" -version = "0.15.22" +version = "0.15.35" authors = ["David Tolnay "] -include = ["/Cargo.toml", "/src/**/*.rs", "/README.md", "/LICENSE-APACHE", "/LICENSE-MIT"] +include = ["/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**/*.rs"] description = "Parser for Rust source code" documentation = "https://docs.rs/syn" readme = "README.md" categories = ["development-tools::procedural-macro-helpers"] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/syn" [package.metadata.docs.rs] all-features = true [package.metadata.playground] all-features = true - -[lib] -name = "syn" - -[[example]] -name = "dump-syntax" -path = "examples/dump-syntax/main.rs" -required-features = ["full", "parsing", "extra-traits"] [dependencies.proc-macro2] version = "0.4.4" default-features = false @@ -45,12 +37,21 @@ default-features = false [dependencies.unicode-xid] version = "0.1" +[dev-dependencies.insta] +version = "0.8" + [dev-dependencies.rayon] version = "1.0" +[dev-dependencies.ref-cast] +version = "0.2" + [dev-dependencies.regex] version = "1.0" +[dev-dependencies.termcolor] +version = "1.0" + [dev-dependencies.walkdir] version = "2.1" diff --git a/vendor/syn/LICENSE-MIT b/vendor/syn/LICENSE-MIT index 5767dea4b1..31aa79387f 100644 --- a/vendor/syn/LICENSE-MIT +++ b/vendor/syn/LICENSE-MIT @@ -1,5 +1,3 @@ -Copyright (c) 2018 Syn Developers - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the diff --git a/vendor/syn/README.md b/vendor/syn/README.md index bd28f61758..c71e5ee7b2 100644 --- a/vendor/syn/README.md +++ b/vendor/syn/README.md @@ -81,12 +81,9 @@ proc-macro = true ```rust extern crate proc_macro; -extern crate syn; - -#[macro_use] -extern crate quote; use proc_macro::TokenStream; +use quote::quote; use syn::{parse_macro_input, DeriveInput}; #[proc_macro_derive(MyMacro)] @@ -185,6 +182,18 @@ warning: come on, pick a more creative name | ^^^ ``` +## Testing + +When testing macros, we often care not just that the macro can be used +successfully but also that when the macro is provided with invalid input it +produces maximally helpful error messages. Consider using the [`trybuild`] crate +to write tests for errors that are emitted by your macro or errors detected by +the Rust compiler in the expanded code following misuse of the macro. Such tests +help avoid regressions from later refactors that mistakenly make an error no +longer trigger or be less helpful than it used to be. + +[`trybuild`]: https://github.com/dtolnay/trybuild + ## Debugging When developing a procedural macro it can be helpful to look at what the @@ -243,17 +252,19 @@ structures on sufficiently new compilers. [proc-macro2]: https://github.com/alexcrichton/proc-macro2 -## License - -Licensed under either of +
- * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +#### License -at your option. + +Licensed under either of
Apache License, Version +2.0 or MIT license at your option. + -### Contribution +
+ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + diff --git a/vendor/syn/build.rs b/vendor/syn/build.rs new file mode 100644 index 0000000000..2b2a419645 --- /dev/null +++ b/vendor/syn/build.rs @@ -0,0 +1,72 @@ +use std::env; +use std::process::Command; +use std::str::{self, FromStr}; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let compiler = match rustc_version() { + Some(compiler) => compiler, + None => return, + }; + + if compiler.minor >= 19 { + println!("cargo:rustc-cfg=syn_can_use_thread_id"); + } + + if compiler.minor >= 20 { + println!("cargo:rustc-cfg=syn_can_use_associated_constants"); + } + + // Macro modularization allows re-exporting the `quote!` macro in 1.30+. + if compiler.minor >= 30 { + println!("cargo:rustc-cfg=syn_can_call_macro_by_path"); + } + + if !compiler.nightly { + println!("cargo:rustc-cfg=syn_disable_nightly_tests"); + } +} + +struct Compiler { + minor: u32, + nightly: bool, +} + +fn rustc_version() -> Option { + let rustc = match env::var_os("RUSTC") { + Some(rustc) => rustc, + None => return None, + }; + + let output = match Command::new(rustc).arg("--version").output() { + Ok(output) => output, + Err(_) => return None, + }; + + let version = match str::from_utf8(&output.stdout) { + Ok(version) => version, + Err(_) => return None, + }; + + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + + let next = match pieces.next() { + Some(next) => next, + None => return None, + }; + + let minor = match u32::from_str(next) { + Ok(minor) => minor, + Err(_) => return None, + }; + + Some(Compiler { + minor: minor, + nightly: version.contains("nightly"), + }) +} diff --git a/vendor/syn/src/attr.rs b/vendor/syn/src/attr.rs index 8a89289dc8..ae90eaa3ac 100644 --- a/vendor/syn/src/attr.rs +++ b/vendor/syn/src/attr.rs @@ -1,11 +1,3 @@ -// Copyright 2018 Syn Developers -// -// Licensed under the Apache License, 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 super::*; use punctuated::Punctuated; @@ -77,11 +69,8 @@ ast_struct! { /// [`Attribute::parse_outer`]: #method.parse_outer /// [`Attribute::parse_inner`]: #method.parse_inner /// - /// ``` - /// #[macro_use] - /// extern crate syn; - /// - /// use syn::{Attribute, Ident, Result}; + /// ```edition2018 + /// use syn::{Attribute, Ident, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses a unit struct with attributes. @@ -105,8 +94,6 @@ ast_struct! { /// }) /// } /// } - /// # - /// # fn main() {} /// ``` pub struct Attribute #manual_extra_traits { pub pound_token: Token![#], @@ -146,8 +133,8 @@ impl Hash for Attribute { } impl Attribute { - /// Parses the tokens after the path as a [`Meta`](enum.Meta.html) if - /// possible. + /// Parses the content of the attribute, consisting of the path and tts, as + /// a [`Meta`](enum.Meta.html) if possible. /// /// Deprecated; use `parse_meta` instead. #[doc(hidden)] @@ -187,8 +174,8 @@ impl Attribute { } } - /// Parses the tokens after the path as a [`Meta`](enum.Meta.html) if - /// possible. + /// Parses the content of the attribute, consisting of the path and tts, as + /// a [`Meta`](enum.Meta.html) if possible. #[cfg(feature = "parsing")] pub fn parse_meta(&self) -> Result { if let Some(ref colon) = self.path.leading_colon { @@ -483,7 +470,7 @@ ast_enum_of_structs! { /// For example if we are developing an attribute macro that is intended to be /// invoked on function items as follows: /// -/// ```rust +/// ```edition2018 /// # const IGNORE: &str = stringify! { /// #[my_attribute(path = "/v1/refresh")] /// # }; @@ -495,14 +482,11 @@ ast_enum_of_structs! { /// The implementation of this macro would want to parse its attribute arguments /// as type `AttributeArgs`. /// -/// ```rust -/// #[macro_use] -/// extern crate syn; -/// +/// ```edition2018 /// extern crate proc_macro; /// /// use proc_macro::TokenStream; -/// use syn::{AttributeArgs, ItemFn}; +/// use syn::{parse_macro_input, AttributeArgs, ItemFn}; /// /// # const IGNORE: &str = stringify! { /// #[proc_macro_attribute] @@ -514,8 +498,6 @@ ast_enum_of_structs! { /// /* ... */ /// # "".parse().unwrap() /// } -/// # -/// # fn main() {} /// ``` pub type AttributeArgs = Vec; diff --git a/vendor/syn/src/buffer.rs b/vendor/syn/src/buffer.rs index e8e8c1a8a8..8c326451eb 100644 --- a/vendor/syn/src/buffer.rs +++ b/vendor/syn/src/buffer.rs @@ -1,19 +1,11 @@ -// Copyright 2018 Syn Developers -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! A stably addressed token buffer supporting efficient traversal based on a //! cheaply copyable cursor. //! //! *This module is available if Syn is built with the `"parsing"` feature.* -// This module is heavily commented as it contains the only unsafe code in Syn, -// and caution should be used when editing it. The public-facing interface is -// 100% safe but the implementation is fragile internally. +// This module is heavily commented as it contains most of the unsafe code in +// Syn, and caution should be used when editing it. The public-facing interface +// is 100% safe but the implementation is fragile internally. #[cfg(all( not(all(target_arch = "wasm32", target_os = "unknown")), @@ -25,6 +17,7 @@ use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenS use std::marker::PhantomData; use std::ptr; +use private; use Lifetime; /// Internal type which is used instead of `TokenTree` to represent a token tree @@ -353,3 +346,21 @@ impl<'a> Cursor<'a> { } } } + +impl private { + #[cfg(procmacro2_semver_exempt)] + pub fn open_span_of_group(cursor: Cursor) -> Span { + match *cursor.entry() { + Entry::Group(ref group, _) => group.span_open(), + _ => cursor.span(), + } + } + + #[cfg(procmacro2_semver_exempt)] + pub fn close_span_of_group(cursor: Cursor) -> Span { + match *cursor.entry() { + Entry::Group(ref group, _) => group.span_close(), + _ => cursor.span(), + } + } +} diff --git a/vendor/syn/src/custom_keyword.rs b/vendor/syn/src/custom_keyword.rs new file mode 100644 index 0000000000..ab3d5b64fe --- /dev/null +++ b/vendor/syn/src/custom_keyword.rs @@ -0,0 +1,252 @@ +/// Define a type that supports parsing and printing a given identifier as if it +/// were a keyword. +/// +/// # Usage +/// +/// As a convention, it is recommended that this macro be invoked within a +/// module called `kw` or `keyword` and that the resulting parser be invoked +/// with a `kw::` or `keyword::` prefix. +/// +/// ```edition2018 +/// mod kw { +/// syn::custom_keyword!(whatever); +/// } +/// ``` +/// +/// The generated syntax tree node supports the following operations just like +/// any built-in keyword token. +/// +/// - [Peeking] — `input.peek(kw::whatever)` +/// +/// - [Parsing] — `input.parse::()?` +/// +/// - [Printing] — `quote!( ... #whatever_token ... )` +/// +/// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)` +/// +/// - Field access to its span — `let sp = whatever_token.span` +/// +/// [Peeking]: parse/struct.ParseBuffer.html#method.peek +/// [Parsing]: parse/struct.ParseBuffer.html#method.parse +/// [Printing]: https://docs.rs/quote/0.6/quote/trait.ToTokens.html +/// [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html +/// +/// # Example +/// +/// This example parses input that looks like `bool = true` or `str = "value"`. +/// The key must be either the identifier `bool` or the identifier `str`. If +/// `bool`, the value may be either `true` or `false`. If `str`, the value may +/// be any string literal. +/// +/// The symbols `bool` and `str` are not reserved keywords in Rust so these are +/// not considered keywords in the `syn::token` module. Like any other +/// identifier that is not a keyword, these can be declared as custom keywords +/// by crates that need to use them as such. +/// +/// ```edition2018 +/// use syn::{LitBool, LitStr, Result, Token}; +/// use syn::parse::{Parse, ParseStream}; +/// +/// mod kw { +/// syn::custom_keyword!(bool); +/// syn::custom_keyword!(str); +/// } +/// +/// enum Argument { +/// Bool { +/// bool_token: kw::bool, +/// eq_token: Token![=], +/// value: LitBool, +/// }, +/// Str { +/// str_token: kw::str, +/// eq_token: Token![=], +/// value: LitStr, +/// }, +/// } +/// +/// impl Parse for Argument { +/// fn parse(input: ParseStream) -> Result { +/// let lookahead = input.lookahead1(); +/// if lookahead.peek(kw::bool) { +/// Ok(Argument::Bool { +/// bool_token: input.parse::()?, +/// eq_token: input.parse()?, +/// value: input.parse()?, +/// }) +/// } else if lookahead.peek(kw::str) { +/// Ok(Argument::Str { +/// str_token: input.parse::()?, +/// eq_token: input.parse()?, +/// value: input.parse()?, +/// }) +/// } else { +/// Err(lookahead.error()) +/// } +/// } +/// } +/// ``` +#[macro_export(local_inner_macros)] +macro_rules! custom_keyword { + ($ident:ident) => { + #[allow(non_camel_case_types)] + pub struct $ident { + pub span: $crate::export::Span, + } + + #[doc(hidden)] + #[allow(non_snake_case)] + pub fn $ident<__S: $crate::export::IntoSpans<[$crate::export::Span; 1]>>( + span: __S, + ) -> $ident { + $ident { + span: $crate::export::IntoSpans::into_spans(span)[0], + } + } + + impl $crate::export::Default for $ident { + fn default() -> Self { + $ident { + span: $crate::export::Span::call_site(), + } + } + } + + impl_parse_for_custom_keyword!($ident); + impl_to_tokens_for_custom_keyword!($ident); + impl_clone_for_custom_keyword!($ident); + impl_extra_traits_for_custom_keyword!($ident); + }; +} + +// Not public API. +#[cfg(feature = "parsing")] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_parse_for_custom_keyword { + ($ident:ident) => { + // For peek. + impl $crate::token::CustomToken for $ident { + fn peek(cursor: $crate::buffer::Cursor) -> $crate::export::bool { + if let Some((ident, _rest)) = cursor.ident() { + ident == stringify!($ident) + } else { + false + } + } + + fn display() -> &'static $crate::export::str { + concat!("`", stringify!($ident), "`") + } + } + + impl $crate::parse::Parse for $ident { + fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> { + input.step(|cursor| { + if let $crate::export::Some((ident, rest)) = cursor.ident() { + if ident == stringify!($ident) { + return $crate::export::Ok(($ident { span: ident.span() }, rest)); + } + } + $crate::export::Err(cursor.error(concat!( + "expected `", + stringify!($ident), + "`" + ))) + }) + } + } + }; +} + +// Not public API. +#[cfg(not(feature = "parsing"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_parse_for_custom_keyword { + ($ident:ident) => {}; +} + +// Not public API. +#[cfg(feature = "printing")] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_to_tokens_for_custom_keyword { + ($ident:ident) => { + impl $crate::export::ToTokens for $ident { + fn to_tokens(&self, tokens: &mut $crate::export::TokenStream2) { + let ident = $crate::Ident::new(stringify!($ident), self.span); + $crate::export::TokenStreamExt::append(tokens, ident); + } + } + }; +} + +// Not public API. +#[cfg(not(feature = "printing"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_to_tokens_for_custom_keyword { + ($ident:ident) => {}; +} + +// Not public API. +#[cfg(feature = "clone-impls")] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_clone_for_custom_keyword { + ($ident:ident) => { + impl $crate::export::Copy for $ident {} + + impl $crate::export::Clone for $ident { + fn clone(&self) -> Self { + *self + } + } + }; +} + +// Not public API. +#[cfg(not(feature = "clone-impls"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_clone_for_custom_keyword { + ($ident:ident) => {}; +} + +// Not public API. +#[cfg(feature = "extra-traits")] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_extra_traits_for_custom_keyword { + ($ident:ident) => { + impl $crate::export::Debug for $ident { + fn fmt(&self, f: &mut $crate::export::Formatter) -> $crate::export::fmt::Result { + $crate::export::Formatter::write_str( + f, + concat!("Keyword [", stringify!($ident), "]"), + ) + } + } + + impl $crate::export::Eq for $ident {} + + impl $crate::export::PartialEq for $ident { + fn eq(&self, _other: &Self) -> $crate::export::bool { + true + } + } + + impl $crate::export::Hash for $ident { + fn hash<__H: $crate::export::Hasher>(&self, _state: &mut __H) {} + } + }; +} + +// Not public API. +#[cfg(not(feature = "extra-traits"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_extra_traits_for_custom_keyword { + ($ident:ident) => {}; +} diff --git a/vendor/syn/src/custom_punctuation.rs b/vendor/syn/src/custom_punctuation.rs new file mode 100644 index 0000000000..8d7d4443f8 --- /dev/null +++ b/vendor/syn/src/custom_punctuation.rs @@ -0,0 +1,309 @@ +/// Define a type that supports parsing and printing a multi-character symbol +/// as if it were a punctuation token. +/// +/// # Usage +/// +/// ```edition2018 +/// syn::custom_punctuation!(LeftRightArrow, <=>); +/// ``` +/// +/// The generated syntax tree node supports the following operations just like +/// any built-in punctuation token. +/// +/// - [Peeking] — `input.peek(LeftRightArrow)` +/// +/// - [Parsing] — `input.parse::()?` +/// +/// - [Printing] — `quote!( ... #lrarrow ... )` +/// +/// - Construction from a [`Span`] — `let lrarrow = LeftRightArrow(sp)` +/// +/// - Construction from multiple [`Span`] — `let lrarrow = LeftRightArrow([sp, sp, sp])` +/// +/// - Field access to its spans — `let spans = lrarrow.spans` +/// +/// [Peeking]: parse/struct.ParseBuffer.html#method.peek +/// [Parsing]: parse/struct.ParseBuffer.html#method.parse +/// [Printing]: https://docs.rs/quote/0.6/quote/trait.ToTokens.html +/// [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html +/// +/// # Example +/// +/// ```edition2018 +/// use proc_macro2::{TokenStream, TokenTree}; +/// use syn::parse::{Parse, ParseStream, Peek, Result}; +/// use syn::punctuated::Punctuated; +/// use syn::Expr; +/// +/// syn::custom_punctuation!(PathSeparator, ); +/// +/// // expr expr expr ... +/// struct PathSegments { +/// segments: Punctuated, +/// } +/// +/// impl Parse for PathSegments { +/// fn parse(input: ParseStream) -> Result { +/// let mut segments = Punctuated::new(); +/// +/// let first = parse_until(input, PathSeparator)?; +/// segments.push_value(syn::parse2(first)?); +/// +/// while input.peek(PathSeparator) { +/// segments.push_punct(input.parse()?); +/// +/// let next = parse_until(input, PathSeparator)?; +/// segments.push_value(syn::parse2(next)?); +/// } +/// +/// Ok(PathSegments { segments }) +/// } +/// } +/// +/// fn parse_until(input: ParseStream, end: E) -> Result { +/// let mut tokens = TokenStream::new(); +/// while !input.is_empty() && !input.peek(end) { +/// let next: TokenTree = input.parse()?; +/// tokens.extend(Some(next)); +/// } +/// Ok(tokens) +/// } +/// +/// fn main() { +/// let input = r#" a::b c::d::e "#; +/// let _: PathSegments = syn::parse_str(input).unwrap(); +/// } +/// ``` +#[macro_export(local_inner_macros)] +macro_rules! custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + pub struct $ident { + pub spans: custom_punctuation_repr!($($tt)+), + } + + #[doc(hidden)] + #[allow(non_snake_case)] + pub fn $ident<__S: $crate::export::IntoSpans>( + spans: __S, + ) -> $ident { + let _validate_len = 0 $(+ custom_punctuation_len!(strict, $tt))*; + $ident { + spans: $crate::export::IntoSpans::into_spans(spans) + } + } + + impl $crate::export::Default for $ident { + fn default() -> Self { + $ident($crate::export::Span::call_site()) + } + } + + impl_parse_for_custom_punctuation!($ident, $($tt)+); + impl_to_tokens_for_custom_punctuation!($ident, $($tt)+); + impl_clone_for_custom_punctuation!($ident, $($tt)+); + impl_extra_traits_for_custom_punctuation!($ident, $($tt)+); + }; +} + +// Not public API. +#[cfg(feature = "parsing")] +#[doc(hidden)] +#[macro_export(local_inner_macros)] +macro_rules! impl_parse_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + impl $crate::token::CustomToken for $ident { + fn peek(cursor: $crate::buffer::Cursor) -> bool { + $crate::token::parsing::peek_punct(cursor, stringify_punct!($($tt)+)) + } + + fn display() -> &'static $crate::export::str { + custom_punctuation_concat!("`", stringify_punct!($($tt)+), "`") + } + } + + impl $crate::parse::Parse for $ident { + fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> { + let spans: custom_punctuation_repr!($($tt)+) = + $crate::token::parsing::punct(input, stringify_punct!($($tt)+))?; + Ok($ident(spans)) + } + } + }; +} + +// Not public API. +#[cfg(not(feature = "parsing"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_parse_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => {}; +} + +// Not public API. +#[cfg(feature = "printing")] +#[doc(hidden)] +#[macro_export(local_inner_macros)] +macro_rules! impl_to_tokens_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + impl $crate::export::ToTokens for $ident { + fn to_tokens(&self, tokens: &mut $crate::export::TokenStream2) { + $crate::token::printing::punct(stringify_punct!($($tt)+), &self.spans, tokens) + } + } + }; +} + +// Not public API. +#[cfg(not(feature = "printing"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_to_tokens_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => {}; +} + +// Not public API. +#[cfg(feature = "clone-impls")] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_clone_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + impl $crate::export::Copy for $ident {} + + impl $crate::export::Clone for $ident { + fn clone(&self) -> Self { + *self + } + } + }; +} + +// Not public API. +#[cfg(not(feature = "clone-impls"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_clone_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => {}; +} + +// Not public API. +#[cfg(feature = "extra-traits")] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_extra_traits_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + impl $crate::export::Debug for $ident { + fn fmt(&self, f: &mut $crate::export::Formatter) -> $crate::export::fmt::Result { + $crate::export::Formatter::write_str(f, stringify!($ident)) + } + } + + impl $crate::export::Eq for $ident {} + + impl $crate::export::PartialEq for $ident { + fn eq(&self, _other: &Self) -> $crate::export::bool { + true + } + } + + impl $crate::export::Hash for $ident { + fn hash<__H: $crate::export::Hasher>(&self, _state: &mut __H) {} + } + }; +} + +// Not public API. +#[cfg(not(feature = "extra-traits"))] +#[doc(hidden)] +#[macro_export] +macro_rules! impl_extra_traits_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => {}; +} + +// Not public API. +#[doc(hidden)] +#[macro_export(local_inner_macros)] +macro_rules! custom_punctuation_repr { + ($($tt:tt)+) => { + [$crate::export::Span; 0 $(+ custom_punctuation_len!(lenient, $tt))+] + }; +} + +// Not public API. +#[doc(hidden)] +#[macro_export(local_inner_macros)] +#[cfg_attr(rustfmt, rustfmt_skip)] +macro_rules! custom_punctuation_len { + ($mode:ident, +) => { 1 }; + ($mode:ident, +=) => { 2 }; + ($mode:ident, &) => { 1 }; + ($mode:ident, &&) => { 2 }; + ($mode:ident, &=) => { 2 }; + ($mode:ident, @) => { 1 }; + ($mode:ident, !) => { 1 }; + ($mode:ident, ^) => { 1 }; + ($mode:ident, ^=) => { 2 }; + ($mode:ident, :) => { 1 }; + ($mode:ident, ::) => { 2 }; + ($mode:ident, ,) => { 1 }; + ($mode:ident, /) => { 1 }; + ($mode:ident, /=) => { 2 }; + ($mode:ident, .) => { 1 }; + ($mode:ident, ..) => { 2 }; + ($mode:ident, ...) => { 3 }; + ($mode:ident, ..=) => { 3 }; + ($mode:ident, =) => { 1 }; + ($mode:ident, ==) => { 2 }; + ($mode:ident, >=) => { 2 }; + ($mode:ident, >) => { 1 }; + ($mode:ident, <=) => { 2 }; + ($mode:ident, <) => { 1 }; + ($mode:ident, *=) => { 2 }; + ($mode:ident, !=) => { 2 }; + ($mode:ident, |) => { 1 }; + ($mode:ident, |=) => { 2 }; + ($mode:ident, ||) => { 2 }; + ($mode:ident, #) => { 1 }; + ($mode:ident, ?) => { 1 }; + ($mode:ident, ->) => { 2 }; + ($mode:ident, <-) => { 2 }; + ($mode:ident, %) => { 1 }; + ($mode:ident, %=) => { 2 }; + ($mode:ident, =>) => { 2 }; + ($mode:ident, ;) => { 1 }; + ($mode:ident, <<) => { 2 }; + ($mode:ident, <<=) => { 3 }; + ($mode:ident, >>) => { 2 }; + ($mode:ident, >>=) => { 3 }; + ($mode:ident, *) => { 1 }; + ($mode:ident, -) => { 1 }; + ($mode:ident, -=) => { 2 }; + ($mode:ident, ~) => { 1 }; + (lenient, $tt:tt) => { 0 }; + (strict, $tt:tt) => {{ custom_punctuation_unexpected!($tt); 0 }}; +} + +// Not public API. +#[doc(hidden)] +#[macro_export] +macro_rules! custom_punctuation_unexpected { + () => {}; +} + +// Not public API. +#[doc(hidden)] +#[macro_export] +macro_rules! stringify_punct { + ($($tt:tt)+) => { + concat!($(stringify!($tt)),+) + }; +} + +// Not public API. +// Without this, local_inner_macros breaks when looking for concat! +#[doc(hidden)] +#[macro_export] +macro_rules! custom_punctuation_concat { + ($($tt:tt)*) => { + concat!($($tt)*) + }; +} diff --git a/vendor/syn/src/data.rs b/vendor/syn/src/data.rs index 4f0986a3f1..f54f5b9afe 100644 --- a/vendor/syn/src/data.rs +++ b/vendor/syn/src/data.rs @@ -1,11 +1,3 @@ -// Copyright 2018 Syn Developers -// -// Licensed under the Apache License, 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 super::*; use punctuated::Punctuated; diff --git a/vendor/syn/src/derive.rs b/vendor/syn/src/derive.rs index 5c1bb17c6e..48ae7e46ee 100644 --- a/vendor/syn/src/derive.rs +++ b/vendor/syn/src/derive.rs @@ -1,11 +1,3 @@ -// Copyright 2018 Syn Developers -// -// Licensed under the Apache License, 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 super::*; use punctuated::Punctuated; diff --git a/vendor/syn/src/error.rs b/vendor/syn/src/error.rs index 957e5781bd..097a6b84ad 100644 --- a/vendor/syn/src/error.rs +++ b/vendor/syn/src/error.rs @@ -1,13 +1,5 @@ -// Copyright 2018 Syn Developers -// -// Licensed under the Apache License, 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; -use std::fmt::{self, Display}; +use std::fmt::{self, Debug, Display}; use std::iter::FromIterator; use proc_macro2::{ @@ -18,6 +10,8 @@ use quote::ToTokens; #[cfg(feature = "parsing")] use buffer::Cursor; +#[cfg(all(procmacro2_semver_exempt, feature = "parsing"))] +use private; use thread::ThreadBound; /// The result of a Syn parser. @@ -30,7 +24,6 @@ pub type Result = std::result::Result; /// [module documentation]: index.html /// /// *This type is available if Syn is built with the `"parsing"` feature.* -#[derive(Debug)] pub struct Error { // Span is implemented as an index into a thread-local interner to keep the // size small. It is not safe to access from a different thread. We want @@ -59,11 +52,8 @@ impl Error { /// /// # Example /// - /// ``` - /// #[macro_use] - /// extern crate syn; - /// - /// use syn::{Error, Ident, LitStr, Result}; + /// ```edition2018 + /// use syn::{Error, Ident, LitStr, Result, Token}; /// use syn::parse::ParseStream; /// /// // Parses input that looks like `name = "string"` where the key must be @@ -80,8 +70,6 @@ impl Error { /// let s: LitStr = input.parse()?; /// Ok(s) /// } - /// # - /// # fn main() {} /// ``` pub fn new(span: Span, message: T) -> Self { Error { @@ -184,7 +172,17 @@ pub fn new_at(scope: Span, cursor: Cursor, message: T) -> Error { if cursor.eof() { Error::new(scope, format!("unexpected end of input, {}", message)) } else { - Error::new(cursor.span(), message) + #[cfg(procmacro2_semver_exempt)] + let span = private::open_span_of_group(cursor); + #[cfg(not(procmacro2_semver_exempt))] + let span = cursor.span(); + Error::new(span, message) + } +} + +impl Debug for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.debug_tuple("Error").field(&self.message).finish() } } diff --git a/vendor/syn/src/expr.rs b/vendor/syn/src/expr.rs index 85f02e4b2d..05cfae0ada 100644 --- a/vendor/syn/src/expr.rs +++ b/vendor/syn/src/expr.rs @@ -1,11 +1,3 @@ -// Copyright 2018 Syn Developers -// -// Licensed under the Apache License, 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 super::*; use proc_macro2::{Span, TokenStream}; use punctuated::Punctuated; @@ -27,7 +19,7 @@ ast_enum_of_structs! { /// This type is a syntax tree enum. In Syn this and other syntax tree enums /// are designed to be traversed using the following rebinding idiom. /// - /// ``` + /// ```edition2018 /// # use syn::Expr; /// # /// # fn example(expr: Expr) { @@ -44,9 +36,10 @@ ast_enum_of_structs! { /// Expr::If(expr) => { /// /* ... */ /// } + /// /// /* ... */ /// # _ => {} - /// } + /// # } /// # } /// ``` /// @@ -58,28 +51,15 @@ ast_enum_of_structs! { /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`. /// - /// The pattern is similar if the input expression is borrowed: - /// - /// ``` - /// # use syn::Expr; - /// # - /// # fn example(expr: &Expr) { - /// match *expr { - /// Expr::MethodCall(ref expr) => { - /// # } - /// # _ => {} - /// # } - /// # } - /// ``` - /// /// This approach avoids repeating the variant names twice on every line. /// - /// ``` + /// ```edition2018 /// # use syn::{Expr, ExprMethodCall}; /// # /// # fn example(expr: Expr) { - /// # match expr { - /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive + /// // Repetitive; recommend not doing this. + /// match expr { + /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { /// # } /// # _ => {} /// # } @@ -89,13 +69,13 @@ ast_enum_of_structs! { /// In general, the name to which a syntax tree enum variant is bound should /// be a suitable name for the complete syntax tree enum type. /// - /// ``` + /// ```edition2018 /// # use syn::{Expr, ExprField}; /// # - /// # fn example(discriminant: &ExprField) { + /// # fn example(discriminant: ExprField) { /// // Binding is called `base` which is the name I would use if I were /// // assigning `*discriminant.base` without an `if let`. - /// if let Expr::Tuple(ref base) = *discriminant.base { + /// if let Expr::Tuple(base) = *discriminant.base { /// # } /// # } /// ``` @@ -807,8 +787,8 @@ ast_enum_of_structs! { /// A path pattern like `Color::Red`, optionally qualified with a /// self-type. /// - /// Unquailfied path patterns can legally refer to variants, structs, - /// constants or associated constants. Quailfied path patterns like + /// Unqualified path patterns can legally refer to variants, structs, + /// constants or associated constants. Qualified path patterns like /// `::B::C` and `::B::C` can only legally refer to /// associated constants. /// @@ -919,7 +899,7 @@ ast_struct! { /// /// As in: /// - /// ```rust + /// ```edition2018 /// # fn f() -> bool { /// # let n = 0; /// match n { @@ -1014,7 +994,6 @@ pub mod parsing { enum Precedence { Any, Assign, - Placement, Range, Or, And, @@ -1131,23 +1110,6 @@ pub mod parsing { eq_token: eq_token, right: Box::new(rhs), }); - } else if Precedence::Placement >= base && input.peek(Token![<-]) { - let arrow_token: Token![<-] = input.parse()?; - let mut rhs = unary_expr(input, allow_struct)?; - loop { - let next = peek_precedence(input); - if next > Precedence::Placement { - rhs = parse_expr(input, rhs, allow_struct, next)?; - } else { - break; - } - } - lhs = Expr::InPlace(ExprInPlace { - attrs: Vec::new(), - place: Box::new(lhs), - arrow_token: arrow_token, - value: Box::new(rhs), - }); } else if Precedence::Range >= base && input.peek(Token![..]) { let limits: RangeLimits = input.parse()?; let rhs = if input.is_empty() @@ -1251,8 +1213,6 @@ pub mod parsing { Precedence::of(&op) } else if input.peek(Token![=]) && !input.peek(Token![=>]) { Precedence::Assign - } else if input.peek(Token![<-]) { - Precedence::Placement } else if input.peek(Token![..]) { Precedence::Range } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) { @@ -1472,7 +1432,7 @@ pub mod parsing { if input.peek(token::Group) { input.call(expr_group).map(Expr::Group) } else if input.peek(Lit) { - input.call(expr_lit).map(Expr::Lit) + input.parse().map(Expr::Lit) } else if input.peek(Token![async]) && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace)) { @@ -1508,15 +1468,15 @@ pub mod parsing { } else if input.peek(Token![let]) { input.call(expr_let).map(Expr::Let) } else if input.peek(Token![if]) { - input.call(expr_if).map(Expr::If) + input.parse().map(Expr::If) } else if input.peek(Token![while]) { - input.call(expr_while).map(Expr::While) + input.parse().map(Expr::While) } else if input.peek(Token![for]) { - input.call(expr_for_loop).map(Expr::ForLoop) + input.parse().map(Expr::ForLoop) } else if input.peek(Token![loop]) { - input.call(expr_loop).map(Expr::Loop) + input.parse().map(Expr::Loop) } else if input.peek(Token![match]) { - input.call(expr_match).map(Expr::Match) + input.parse().map(Expr::Match) } else if input.peek(Token![yield]) { input.call(expr_yield).map(Expr::Yield) } else if input.peek(Token![unsafe]) { @@ -1528,11 +1488,11 @@ pub mod parsing { } else if input.peek(Lifetime) { let the_label: Label = input.parse()?; let mut expr = if input.peek(Token![while]) { - Expr::While(input.call(expr_while)?) + Expr::While(input.parse()?) } else if input.peek(Token![for]) { - Expr::ForLoop(input.call(expr_for_loop)?) + Expr::ForLoop(input.parse()?) } else if input.peek(Token![loop]) { - Expr::Loop(input.call(expr_loop)?) + Expr::Loop(input.parse()?) } else if input.peek(token::Brace) { Expr::Block(input.call(expr_block)?) } else { @@ -1554,7 +1514,7 @@ pub mod parsing { #[cfg(not(feature = "full"))] fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result { if input.peek(Lit) { - input.call(expr_lit).map(Expr::Lit) + input.parse().map(Expr::Lit) } else if input.peek(token::Paren) { input.call(expr_paren).map(Expr::Paren) } else if input.peek(Ident) @@ -1703,15 +1663,15 @@ pub mod parsing { fn expr_early(input: ParseStream) -> Result { let mut attrs = input.call(Attribute::parse_outer)?; let mut expr = if input.peek(Token![if]) { - Expr::If(input.call(expr_if)?) + Expr::If(input.parse()?) } else if input.peek(Token![while]) { - Expr::While(input.call(expr_while)?) + Expr::While(input.parse()?) } else if input.peek(Token![for]) { - Expr::ForLoop(input.call(expr_for_loop)?) + Expr::ForLoop(input.parse()?) } else if input.peek(Token![loop]) { - Expr::Loop(input.call(expr_loop)?) + Expr::Loop(input.parse()?) } else if input.peek(Token![match]) { - Expr::Match(input.call(expr_match)?) + Expr::Match(input.parse()?) } else if input.peek(Token![try]) && input.peek2(token::Brace) { Expr::TryBlock(input.call(expr_try_block)?) } else if input.peek(Token![unsafe]) { @@ -1743,11 +1703,13 @@ pub mod parsing { Ok(expr) } - pub fn expr_lit(input: ParseStream) -> Result { - Ok(ExprLit { - attrs: Vec::new(), - lit: input.parse()?, - }) + impl Parse for ExprLit { + fn parse(input: ParseStream) -> Result { + Ok(ExprLit { + attrs: Vec::new(), + lit: input.parse()?, + }) + } } #[cfg(feature = "full")] @@ -1783,6 +1745,7 @@ pub mod parsing { let_token: input.parse()?, pats: { let mut pats = Punctuated::new(); + input.parse::>()?; let value: Pat = input.parse()?; pats.push_value(value); while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { @@ -1799,20 +1762,22 @@ pub mod parsing { } #[cfg(feature = "full")] - fn expr_if(input: ParseStream) -> Result { - Ok(ExprIf { - attrs: Vec::new(), - if_token: input.parse()?, - cond: Box::new(input.call(expr_no_struct)?), - then_branch: input.parse()?, - else_branch: { - if input.peek(Token![else]) { - Some(input.call(else_block)?) - } else { - None - } - }, - }) + impl Parse for ExprIf { + fn parse(input: ParseStream) -> Result { + Ok(ExprIf { + attrs: Vec::new(), + if_token: input.parse()?, + cond: Box::new(input.call(expr_no_struct)?), + then_branch: input.parse()?, + else_branch: { + if input.peek(Token![else]) { + Some(input.call(else_block)?) + } else { + None + } + }, + }) + } } #[cfg(feature = "full")] @@ -1821,7 +1786,7 @@ pub mod parsing { let lookahead = input.lookahead1(); let else_branch = if input.peek(Token![if]) { - input.call(expr_if).map(Expr::If)? + input.parse().map(Expr::If)? } else if input.peek(token::Brace) { Expr::Block(ExprBlock { attrs: Vec::new(), @@ -1836,74 +1801,145 @@ pub mod parsing { } #[cfg(feature = "full")] - fn expr_for_loop(input: ParseStream) -> Result { - let label: Option
diff --git a/vendor/mdbook/src/theme/mod.rs b/vendor/mdbook/src/theme/mod.rs index 37d373eff3..aab96db732 100644 --- a/vendor/mdbook/src/theme/mod.rs +++ b/vendor/mdbook/src/theme/mod.rs @@ -9,33 +9,29 @@ use std::fs::File; use std::io::Read; use std::path::Path; -use errors::*; - -pub static INDEX: &'static [u8] = include_bytes!("index.hbs"); -pub static HEADER: &'static [u8] = include_bytes!("header.hbs"); -pub static CHROME_CSS: &'static [u8] = include_bytes!("css/chrome.css"); -pub static GENERAL_CSS: &'static [u8] = include_bytes!("css/general.css"); -pub static PRINT_CSS: &'static [u8] = include_bytes!("css/print.css"); -pub static VARIABLES_CSS: &'static [u8] = include_bytes!("css/variables.css"); -pub static FAVICON: &'static [u8] = include_bytes!("favicon.png"); -pub static JS: &'static [u8] = include_bytes!("book.js"); -pub static HIGHLIGHT_JS: &'static [u8] = include_bytes!("highlight.js"); -pub static TOMORROW_NIGHT_CSS: &'static [u8] = include_bytes!("tomorrow-night.css"); -pub static HIGHLIGHT_CSS: &'static [u8] = include_bytes!("highlight.css"); -pub static AYU_HIGHLIGHT_CSS: &'static [u8] = include_bytes!("ayu-highlight.css"); -pub static CLIPBOARD_JS: &'static [u8] = include_bytes!("clipboard.min.js"); -pub static FONT_AWESOME: &'static [u8] = include_bytes!("FontAwesome/css/font-awesome.min.css"); -pub static FONT_AWESOME_EOT: &'static [u8] = - include_bytes!("FontAwesome/fonts/fontawesome-webfont.eot"); -pub static FONT_AWESOME_SVG: &'static [u8] = - include_bytes!("FontAwesome/fonts/fontawesome-webfont.svg"); -pub static FONT_AWESOME_TTF: &'static [u8] = - include_bytes!("FontAwesome/fonts/fontawesome-webfont.ttf"); -pub static FONT_AWESOME_WOFF: &'static [u8] = - include_bytes!("FontAwesome/fonts/fontawesome-webfont.woff"); -pub static FONT_AWESOME_WOFF2: &'static [u8] = +use crate::errors::*; + +pub static INDEX: &[u8] = include_bytes!("index.hbs"); +pub static HEADER: &[u8] = include_bytes!("header.hbs"); +pub static CHROME_CSS: &[u8] = include_bytes!("css/chrome.css"); +pub static GENERAL_CSS: &[u8] = include_bytes!("css/general.css"); +pub static PRINT_CSS: &[u8] = include_bytes!("css/print.css"); +pub static VARIABLES_CSS: &[u8] = include_bytes!("css/variables.css"); +pub static FAVICON: &[u8] = include_bytes!("favicon.png"); +pub static JS: &[u8] = include_bytes!("book.js"); +pub static HIGHLIGHT_JS: &[u8] = include_bytes!("highlight.js"); +pub static TOMORROW_NIGHT_CSS: &[u8] = include_bytes!("tomorrow-night.css"); +pub static HIGHLIGHT_CSS: &[u8] = include_bytes!("highlight.css"); +pub static AYU_HIGHLIGHT_CSS: &[u8] = include_bytes!("ayu-highlight.css"); +pub static CLIPBOARD_JS: &[u8] = include_bytes!("clipboard.min.js"); +pub static FONT_AWESOME: &[u8] = include_bytes!("FontAwesome/css/font-awesome.min.css"); +pub static FONT_AWESOME_EOT: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.eot"); +pub static FONT_AWESOME_SVG: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.svg"); +pub static FONT_AWESOME_TTF: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.ttf"); +pub static FONT_AWESOME_WOFF: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.woff"); +pub static FONT_AWESOME_WOFF2: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.woff2"); -pub static FONT_AWESOME_OTF: &'static [u8] = include_bytes!("FontAwesome/fonts/FontAwesome.otf"); +pub static FONT_AWESOME_OTF: &[u8] = include_bytes!("FontAwesome/fonts/FontAwesome.otf"); /// The `Theme` struct should be used instead of the static variables because /// the `new()` method will look if the user has a theme directory in their diff --git a/vendor/mdbook/src/theme/searcher/mod.rs b/vendor/mdbook/src/theme/searcher/mod.rs index c80441d0a8..d5029db16f 100644 --- a/vendor/mdbook/src/theme/searcher/mod.rs +++ b/vendor/mdbook/src/theme/searcher/mod.rs @@ -1,6 +1,6 @@ //! Theme dependencies for in-browser search. Not included in mdbook when //! the "search" cargo feature is disabled. -pub static JS: &'static [u8] = include_bytes!("searcher.js"); -pub static MARK_JS: &'static [u8] = include_bytes!("mark.min.js"); -pub static ELASTICLUNR_JS: &'static [u8] = include_bytes!("elasticlunr.min.js"); +pub static JS: &[u8] = include_bytes!("searcher.js"); +pub static MARK_JS: &[u8] = include_bytes!("mark.min.js"); +pub static ELASTICLUNR_JS: &[u8] = include_bytes!("elasticlunr.min.js"); diff --git a/vendor/mdbook/src/theme/tomorrow-night.css b/vendor/mdbook/src/theme/tomorrow-night.css index 9788e0846b..f71979258d 100644 --- a/vendor/mdbook/src/theme/tomorrow-night.css +++ b/vendor/mdbook/src/theme/tomorrow-night.css @@ -94,3 +94,11 @@ .xml .hljs-cdata { opacity: 0.5; } + +.hljs-addition { + color: #718c00; +} + +.hljs-deletion { + color: #c82829; +} diff --git a/vendor/mdbook/src/utils/fs.rs b/vendor/mdbook/src/utils/fs.rs index 4ac591270e..97d19d2fb2 100644 --- a/vendor/mdbook/src/utils/fs.rs +++ b/vendor/mdbook/src/utils/fs.rs @@ -1,4 +1,5 @@ -use errors::*; +use crate::errors::*; +use std::convert::Into; use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::{Component, Path, PathBuf}; @@ -28,7 +29,7 @@ pub fn normalize_path(path: &str) -> String { pub fn write_file>(build_dir: &Path, filename: P, content: &[u8]) -> Result<()> { let path = build_dir.join(filename); - create_file(&path)?.write_all(content).map_err(|e| e.into()) + create_file(&path)?.write_all(content).map_err(Into::into) } /// Takes a path and returns a path containing just enough `../` to point to @@ -38,8 +39,6 @@ pub fn write_file>(build_dir: &Path, filename: P, content: &[u8]) /// directory from where the path starts. /// /// ```rust -/// # extern crate mdbook; -/// # /// # use std::path::Path; /// # use mdbook::utils::fs::path_to_root; /// # @@ -85,7 +84,7 @@ pub fn create_file(path: &Path) -> Result { fs::create_dir_all(p)?; } - File::create(path).map_err(|e| e.into()) + File::create(path).map_err(Into::into) } /// Removes all the content of a directory but not the directory itself @@ -187,8 +186,6 @@ pub fn copy_files_except_ext( #[cfg(test)] mod tests { - extern crate tempfile; - use super::copy_files_except_ext; use std::fs; @@ -196,43 +193,44 @@ mod tests { fn copy_files_except_ext_test() { let tmp = match tempfile::TempDir::new() { Ok(t) => t, - Err(_) => panic!("Could not create a temp dir"), + Err(e) => panic!("Could not create a temp dir: {}", e), }; // Create a couple of files - if let Err(_) = fs::File::create(&tmp.path().join("file.txt")) { - panic!("Could not create file.txt") + if let Err(err) = fs::File::create(&tmp.path().join("file.txt")) { + panic!("Could not create file.txt: {}", err); } - if let Err(_) = fs::File::create(&tmp.path().join("file.md")) { - panic!("Could not create file.md") + if let Err(err) = fs::File::create(&tmp.path().join("file.md")) { + panic!("Could not create file.md: {}", err); } - if let Err(_) = fs::File::create(&tmp.path().join("file.png")) { - panic!("Could not create file.png") + if let Err(err) = fs::File::create(&tmp.path().join("file.png")) { + panic!("Could not create file.png: {}", err); } - if let Err(_) = fs::create_dir(&tmp.path().join("sub_dir")) { - panic!("Could not create sub_dir") + if let Err(err) = fs::create_dir(&tmp.path().join("sub_dir")) { + panic!("Could not create sub_dir: {}", err); } - if let Err(_) = fs::File::create(&tmp.path().join("sub_dir/file.png")) { - panic!("Could not create sub_dir/file.png") + if let Err(err) = fs::File::create(&tmp.path().join("sub_dir/file.png")) { + panic!("Could not create sub_dir/file.png: {}", err); } - if let Err(_) = fs::create_dir(&tmp.path().join("sub_dir_exists")) { - panic!("Could not create sub_dir_exists") + if let Err(err) = fs::create_dir(&tmp.path().join("sub_dir_exists")) { + panic!("Could not create sub_dir_exists: {}", err); } - if let Err(_) = fs::File::create(&tmp.path().join("sub_dir_exists/file.txt")) { - panic!("Could not create sub_dir_exists/file.txt") + if let Err(err) = fs::File::create(&tmp.path().join("sub_dir_exists/file.txt")) { + panic!("Could not create sub_dir_exists/file.txt: {}", err); } // Create output dir - if let Err(_) = fs::create_dir(&tmp.path().join("output")) { - panic!("Could not create output") + if let Err(err) = fs::create_dir(&tmp.path().join("output")) { + panic!("Could not create output: {}", err); } - if let Err(_) = fs::create_dir(&tmp.path().join("output/sub_dir_exists")) { - panic!("Could not create output/sub_dir_exists") + if let Err(err) = fs::create_dir(&tmp.path().join("output/sub_dir_exists")) { + panic!("Could not create output/sub_dir_exists: {}", err); } - match copy_files_except_ext(&tmp.path(), &tmp.path().join("output"), true, &["md"]) { - Err(e) => panic!("Error while executing the function:\n{:?}", e), - Ok(_) => {} + if let Err(e) = + copy_files_except_ext(&tmp.path(), &tmp.path().join("output"), true, &["md"]) + { + panic!("Error while executing the function:\n{:?}", e); } // Check if the correct files where created diff --git a/vendor/mdbook/src/utils/mod.rs b/vendor/mdbook/src/utils/mod.rs index df997d5eb3..0f199fb729 100644 --- a/vendor/mdbook/src/utils/mod.rs +++ b/vendor/mdbook/src/utils/mod.rs @@ -2,19 +2,17 @@ pub mod fs; mod string; -use errors::Error; +use crate::errors::Error; use regex::Regex; -use pulldown_cmark::{ - html, Event, Options, Parser, Tag, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES, -}; +use pulldown_cmark::{html, CowStr, Event, Options, Parser, Tag}; use std::borrow::Cow; pub use self::string::{take_lines, RangeArgument}; /// Replaces multiple consecutive whitespace characters with a single space character. -pub fn collapse_whitespace<'a>(text: &'a str) -> Cow<'a, str> { +pub fn collapse_whitespace(text: &str) -> Cow<'_, str> { lazy_static! { static ref RE: Regex = Regex::new(r"\s\s+").unwrap(); } @@ -34,7 +32,8 @@ pub fn normalize_id(content: &str) -> String { } else { None } - }).collect::() + }) + .collect::() } /// Generate an ID for use with anchors which is derived from a "normalised" @@ -61,38 +60,47 @@ pub fn id_from_content(content: &str) -> String { } // Remove spaces and hashes indicating a header - let trimmed = content.trim().trim_left_matches('#').trim(); + let trimmed = content.trim().trim_start_matches('#').trim(); normalize_id(trimmed) } fn adjust_links<'a>(event: Event<'a>, with_base: &str) -> Event<'a> { lazy_static! { - static ref HTTP_LINK: Regex = Regex::new("^https?://").unwrap(); + static ref SCHEME_LINK: Regex = Regex::new(r"^[a-z][a-z0-9+.-]*:").unwrap(); static ref MD_LINK: Regex = Regex::new(r"(?P.*)\.md(?P#.*)?").unwrap(); } - match event { - Event::Start(Tag::Link(dest, title)) => { - if !HTTP_LINK.is_match(&dest) { - let dest = if !with_base.is_empty() { - format!("{}/{}", with_base, dest) - } else { - dest.clone().into_owned() - }; - - if let Some(caps) = MD_LINK.captures(&dest) { - let mut html_link = [&caps["link"], ".html"].concat(); - - if let Some(anchor) = caps.name("anchor") { - html_link.push_str(anchor.as_str()); - } + fn fix<'a>(dest: CowStr<'a>, base: &str) -> CowStr<'a> { + // Don't modify links with schemes like `https`. + if !SCHEME_LINK.is_match(&dest) { + // This is a relative link, adjust it as necessary. + let mut fixed_link = String::new(); + if !base.is_empty() { + fixed_link.push_str(base); + fixed_link.push_str("/"); + } - return Event::Start(Tag::Link(Cow::from(html_link), title)); + if let Some(caps) = MD_LINK.captures(&dest) { + fixed_link.push_str(&caps["link"]); + fixed_link.push_str(".html"); + if let Some(anchor) = caps.name("anchor") { + fixed_link.push_str(anchor.as_str()); } - } + } else { + fixed_link.push_str(&dest); + }; + return CowStr::from(fixed_link); + } + dest + } - Event::Start(Tag::Link(dest, title)) + match event { + Event::Start(Tag::Link(link_type, dest, title)) => { + Event::Start(Tag::Link(link_type, fix(dest, with_base), title)) + } + Event::Start(Tag::Image(link_type, dest, title)) => { + Event::Start(Tag::Image(link_type, fix(dest, with_base), title)) } _ => event, } @@ -103,14 +111,18 @@ pub fn render_markdown(text: &str, curly_quotes: bool) -> String { render_markdown_with_base(text, curly_quotes, "") } -pub fn render_markdown_with_base(text: &str, curly_quotes: bool, base: &str) -> String { - let mut s = String::with_capacity(text.len() * 3 / 2); - +pub fn new_cmark_parser(text: &str) -> Parser<'_> { let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); + opts.insert(Options::ENABLE_TABLES); + opts.insert(Options::ENABLE_FOOTNOTES); + opts.insert(Options::ENABLE_STRIKETHROUGH); + opts.insert(Options::ENABLE_TASKLISTS); + Parser::new_ext(text, opts) +} - let p = Parser::new_ext(text, opts); +pub fn render_markdown_with_base(text: &str, curly_quotes: bool, base: &str) -> String { + let mut s = String::with_capacity(text.len() * 3 / 2); + let p = new_cmark_parser(text); let mut converter = EventQuoteConverter::new(curly_quotes); let events = p .map(clean_codeblock_headers) @@ -140,28 +152,28 @@ impl EventQuoteConverter { } match event { - Event::Start(Tag::CodeBlock(_)) | Event::Start(Tag::Code) => { + Event::Start(Tag::CodeBlock(_)) => { self.convert_text = false; event } - Event::End(Tag::CodeBlock(_)) | Event::End(Tag::Code) => { + Event::End(Tag::CodeBlock(_)) => { self.convert_text = true; event } Event::Text(ref text) if self.convert_text => { - Event::Text(Cow::from(convert_quotes_to_curly(text))) + Event::Text(CowStr::from(convert_quotes_to_curly(text))) } _ => event, } } } -fn clean_codeblock_headers(event: Event) -> Event { +fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> { match event { Event::Start(Tag::CodeBlock(ref info)) => { let info: String = info.chars().filter(|ch| !ch.is_whitespace()).collect(); - Event::Start(Tag::CodeBlock(Cow::from(info))) + Event::Start(Tag::CodeBlock(CowStr::from(info))) } _ => event, } @@ -195,7 +207,8 @@ fn convert_quotes_to_curly(original_text: &str) -> String { preceded_by_whitespace = original_char.is_whitespace(); converted_char - }).collect() + }) + .collect() } /// Prints a "backtrace" of some `Error`. diff --git a/vendor/mdbook/tests/alternate_backends.rs b/vendor/mdbook/tests/alternative_backends.rs similarity index 95% rename from vendor/mdbook/tests/alternate_backends.rs rename to vendor/mdbook/tests/alternative_backends.rs index 41cf2f8406..ff2ab687ca 100644 --- a/vendor/mdbook/tests/alternate_backends.rs +++ b/vendor/mdbook/tests/alternative_backends.rs @@ -1,7 +1,4 @@ -//! Integration tests to make sure alternate backends work. - -extern crate mdbook; -extern crate tempfile; +//! Integration tests to make sure alternative backends work. use mdbook::config::Config; use mdbook::MDBook; diff --git a/vendor/mdbook/tests/build_process.rs b/vendor/mdbook/tests/build_process.rs index 85750ab32a..10d0b4a9a8 100644 --- a/vendor/mdbook/tests/build_process.rs +++ b/vendor/mdbook/tests/build_process.rs @@ -1,8 +1,6 @@ -extern crate mdbook; - mod dummy_book; -use dummy_book::DummyBook; +use crate::dummy_book::DummyBook; use mdbook::book::Book; use mdbook::config::Config; use mdbook::errors::*; @@ -52,7 +50,7 @@ fn mdbook_runs_preprocessors() { let cfg = Config::default(); let mut book = MDBook::load_with_config(temp.path(), cfg).unwrap(); - book.with_preprecessor(Spy(Arc::clone(&spy))); + book.with_preprocessor(Spy(Arc::clone(&spy))); book.build().unwrap(); let inner = spy.lock().unwrap(); diff --git a/vendor/mdbook/tests/custom_preprocessors.rs b/vendor/mdbook/tests/custom_preprocessors.rs index dd120eab60..8237602de0 100644 --- a/vendor/mdbook/tests/custom_preprocessors.rs +++ b/vendor/mdbook/tests/custom_preprocessors.rs @@ -1,8 +1,6 @@ -extern crate mdbook; - mod dummy_book; -use dummy_book::DummyBook; +use crate::dummy_book::DummyBook; use mdbook::preprocess::{CmdPreprocessor, Preprocessor}; use mdbook::MDBook; @@ -36,7 +34,7 @@ fn ask_the_preprocessor_to_blow_up() { let dummy_book = DummyBook::new(); let temp = dummy_book.build().unwrap(); let mut md = MDBook::load(temp.path()).unwrap(); - md.with_preprecessor(example()); + md.with_preprocessor(example()); md.config .set("preprocessor.nop-preprocessor.blow-up", true) @@ -52,7 +50,7 @@ fn process_the_dummy_book() { let dummy_book = DummyBook::new(); let temp = dummy_book.build().unwrap(); let mut md = MDBook::load(temp.path()).unwrap(); - md.with_preprecessor(example()); + md.with_preprocessor(example()); md.build().unwrap(); } diff --git a/vendor/mdbook/tests/dummy_book/mod.rs b/vendor/mdbook/tests/dummy_book/mod.rs index 4fe24455c3..6ef2c5579c 100644 --- a/vendor/mdbook/tests/dummy_book/mod.rs +++ b/vendor/mdbook/tests/dummy_book/mod.rs @@ -3,9 +3,6 @@ // Not all features are used in all test crates, so... #![allow(dead_code, unused_variables, unused_imports, unused_extern_crates)] -extern crate mdbook; -extern crate tempfile; -extern crate walkdir; use mdbook::errors::*; use mdbook::utils::fs::file_to_string; @@ -13,11 +10,9 @@ use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::Path; -// The funny `self::` here is because we've got an `extern crate ...` and are -// in a submodule -use self::mdbook::MDBook; -use self::tempfile::{Builder as TempFileBuilder, TempDir}; -use self::walkdir::WalkDir; +use mdbook::MDBook; +use tempfile::{Builder as TempFileBuilder, TempDir}; +use walkdir::WalkDir; /// Create a dummy book in a temporary directory, using the contents of /// `SUMMARY_MD` as a guide. @@ -58,8 +53,11 @@ impl DummyBook { })?; let sub_pattern = if self.passing_test { "true" } else { "false" }; - let file_containing_test = temp.path().join("src/first/nested.md"); - replace_pattern_in_file(&file_containing_test, "$TEST_STATUS", sub_pattern)?; + let files_containing_tests = ["src/first/nested.md", "src/first/nested-test.rs"]; + for file in &files_containing_tests { + let path_containing_tests = temp.path().join(file); + replace_pattern_in_file(&path_containing_tests, "$TEST_STATUS", sub_pattern)?; + } Ok(temp) } diff --git a/vendor/mdbook/tests/dummy_book/src/SUMMARY.md b/vendor/mdbook/tests/dummy_book/src/SUMMARY.md index ee2426e4a8..f14f4e21a5 100644 --- a/vendor/mdbook/tests/dummy_book/src/SUMMARY.md +++ b/vendor/mdbook/tests/dummy_book/src/SUMMARY.md @@ -7,6 +7,7 @@ - [Nested Chapter](first/nested.md) - [Includes](first/includes.md) - [Recursive](first/recursive.md) + - [Markdown](first/markdown.md) - [Second Chapter](second.md) - [Nested Chapter](second/nested.md) diff --git a/vendor/mdbook/tests/dummy_book/src/first/markdown.md b/vendor/mdbook/tests/dummy_book/src/first/markdown.md new file mode 100644 index 0000000000..d65d3d389e --- /dev/null +++ b/vendor/mdbook/tests/dummy_book/src/first/markdown.md @@ -0,0 +1,29 @@ +# Markdown tests + +Tests for some markdown output. + +## Tables + +| foo | bar | +| --- | --- | +| baz | bim | + +## Footnotes + +Footnote example[^1], or with a word[^word]. + +[^1]: This is a footnote. + +[^word]: A longer footnote. + With multiple lines. + Third line. + +## Strikethrough + +~~strikethrough example~~ + +## Tasklisks + +- [X] Apples +- [X] Broccoli +- [ ] Carrots diff --git a/vendor/mdbook/tests/dummy_book/src/first/nested-test.rs b/vendor/mdbook/tests/dummy_book/src/first/nested-test.rs new file mode 100644 index 0000000000..2bc46e01a9 --- /dev/null +++ b/vendor/mdbook/tests/dummy_book/src/first/nested-test.rs @@ -0,0 +1 @@ +assert!($TEST_STATUS); diff --git a/vendor/mdbook/tests/dummy_book/src/first/nested.md b/vendor/mdbook/tests/dummy_book/src/first/nested.md index a7a1cdda88..ba064aaf63 100644 --- a/vendor/mdbook/tests/dummy_book/src/first/nested.md +++ b/vendor/mdbook/tests/dummy_book/src/first/nested.md @@ -7,3 +7,7 @@ assert!($TEST_STATUS); ``` ## Some Section + +```rust +{{#include nested-test.rs}} +``` diff --git a/vendor/mdbook/tests/dummy_book/src/second/nested.md b/vendor/mdbook/tests/dummy_book/src/second/nested.md index c3eb3c8fbb..2fa98bebc0 100644 --- a/vendor/mdbook/tests/dummy_book/src/second/nested.md +++ b/vendor/mdbook/tests/dummy_book/src/second/nested.md @@ -1,4 +1,8 @@ # Testing relative links for the print page When we link to [the first section](../first/nested.md), it should work on -both the print page and the non-print page. \ No newline at end of file +both the print page and the non-print page. + +Link [outside](../../std/foo/bar.html). + +![Some image](../images/picture.png) diff --git a/vendor/mdbook/tests/init.rs b/vendor/mdbook/tests/init.rs index f48848c86d..248cb62393 100644 --- a/vendor/mdbook/tests/init.rs +++ b/vendor/mdbook/tests/init.rs @@ -1,9 +1,8 @@ -extern crate mdbook; -extern crate tempfile; - use mdbook::config::Config; use mdbook::MDBook; use std::fs; +use std::fs::File; +use std::io::prelude::*; use std::path::PathBuf; use tempfile::Builder as TempFileBuilder; @@ -27,6 +26,36 @@ fn base_mdbook_init_should_create_default_content() { } } +/// Run `mdbook init` in a directory containing a SUMMARY.md should create the +/// files listed in the summary. +#[test] +fn run_mdbook_init_should_create_content_from_summary() { + let created_files = vec!["intro.md", "first.md", "outro.md"]; + + let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap(); + let src_dir = temp.path().join("src"); + fs::create_dir_all(src_dir.clone()).unwrap(); + static SUMMARY: &str = r#"# Summary + +[intro](intro.md) + +- [First chapter](first.md) + +[outro](outro.md) + +"#; + + let mut summary = File::create(src_dir.join("SUMMARY.md")).unwrap(); + summary.write_all(SUMMARY.as_bytes()).unwrap(); + MDBook::init(temp.path()).build().unwrap(); + + for file in &created_files { + let target = src_dir.join(file); + println!("{}", target.display()); + assert!(target.exists(), "{} doesn't exist", file); + } +} + /// Set some custom arguments for where to place the source and destination /// files, then call `mdbook init`. #[test] diff --git a/vendor/mdbook/tests/parse_existing_summary_files.rs b/vendor/mdbook/tests/parse_existing_summary_files.rs index 0366b5d0fd..5c75b0d55b 100644 --- a/vendor/mdbook/tests/parse_existing_summary_files.rs +++ b/vendor/mdbook/tests/parse_existing_summary_files.rs @@ -1,10 +1,6 @@ //! Some integration tests to make sure the `SUMMARY.md` parser can deal with //! some real-life examples. -extern crate env_logger; -extern crate error_chain; -extern crate mdbook; - use mdbook::book; use std::fs::File; use std::io::Read; diff --git a/vendor/mdbook/tests/rendered_output.rs b/vendor/mdbook/tests/rendered_output.rs index b7777ee7c5..f293fb6dc2 100644 --- a/vendor/mdbook/tests/rendered_output.rs +++ b/vendor/mdbook/tests/rendered_output.rs @@ -1,13 +1,9 @@ -extern crate mdbook; #[macro_use] extern crate pretty_assertions; -extern crate select; -extern crate tempfile; -extern crate walkdir; mod dummy_book; -use dummy_book::{assert_contains_strings, assert_doesnt_contain_strings, DummyBook}; +use crate::dummy_book::{assert_contains_strings, assert_doesnt_contain_strings, DummyBook}; use mdbook::config::Config; use mdbook::errors::*; @@ -22,16 +18,21 @@ use std::path::Path; use tempfile::Builder as TempFileBuilder; use walkdir::{DirEntry, WalkDir}; -const BOOK_ROOT: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/dummy_book"); -const TOC_TOP_LEVEL: &[&'static str] = &[ +const BOOK_ROOT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/dummy_book"); +const TOC_TOP_LEVEL: &[&str] = &[ "1. First Chapter", "2. Second Chapter", "Conclusion", "Dummy Book", "Introduction", ]; -const TOC_SECOND_LEVEL: &[&'static str] = - &["1.1. Nested Chapter", "1.2. Includes", "2.1. Nested Chapter", "1.3. Recursive"]; +const TOC_SECOND_LEVEL: &[&str] = &[ + "1.1. Nested Chapter", + "1.2. Includes", + "1.3. Recursive", + "1.4. Markdown", + "2.1. Nested Chapter", +]; /// Make sure you can load the dummy book and build it without panicking. #[test] @@ -119,7 +120,11 @@ fn check_correct_relative_links_in_print_page() { assert_contains_strings( first.join("print.html"), - &[r##"the first section,"##], + &[ + r##"the first section,"##, + r##"outside"##, + r##"Some image"##, + ], ); } @@ -183,7 +188,7 @@ fn chapter_files_were_rendered_to_html() { let chapter_files = WalkDir::new(&src) .into_iter() .filter_entry(|entry| entry_ends_with(entry, ".md")) - .filter_map(|entry| entry.ok()) + .filter_map(std::result::Result::ok) .map(|entry| entry.path().to_path_buf()) .filter(|path| path.file_name().and_then(OsStr::to_str) != Some("SUMMARY.md")); @@ -323,7 +328,10 @@ fn able_to_include_files_in_chapters() { let includes = temp.path().join("book/first/includes.html"); - let summary_strings = &["

Summary

", ">First Chapter"]; + let summary_strings = &[ + r##"

Summary

"##, + ">First Chapter", + ]; assert_contains_strings(&includes, summary_strings); assert_doesnt_contain_strings(&includes, &["{{#include ../SUMMARY.md::}}"]); @@ -386,7 +394,7 @@ fn by_default_mdbook_use_index_preprocessor_to_convert_readme_to_index() { "First README", ]; assert_contains_strings(&first_index, &expected_strings); - assert_doesnt_contain_strings(&first_index, &vec!["README.html"]); + assert_doesnt_contain_strings(&first_index, &["README.html"]); let second_index = temp.path().join("book").join("second").join("index.html"); let unexpected_strings = vec!["Second README"]; @@ -399,7 +407,7 @@ fn theme_dir_overrides_work_correctly() { let book_dir = book_dir.path(); let theme_dir = book_dir.join("theme"); - let mut index = ::mdbook::theme::INDEX.to_vec(); + let mut index = mdbook::theme::INDEX.to_vec(); index.extend_from_slice(b"\n"); write_file(&theme_dir, "index.hbs", &index).unwrap(); @@ -411,10 +419,55 @@ fn theme_dir_overrides_work_correctly() { dummy_book::assert_contains_strings(built_index, &["This is a modified index.hbs!"]); } +#[test] +fn no_index_for_print_html() { + let temp = DummyBook::new().build().unwrap(); + let md = MDBook::load(temp.path()).unwrap(); + md.build().unwrap(); + + let print_html = temp.path().join("book/print.html"); + assert_contains_strings(print_html, &[r##"noindex"##]); + + let index_html = temp.path().join("book/index.html"); + assert_doesnt_contain_strings(index_html, &[r##"noindex"##]); +} + +#[test] +fn markdown_options() { + let temp = DummyBook::new().build().unwrap(); + let md = MDBook::load(temp.path()).unwrap(); + md.build().unwrap(); + + let path = temp.path().join("book/first/markdown.html"); + assert_contains_strings( + &path, + &[ + "foo", + "bar", + "baz", + "bim", + ], + ); + assert_contains_strings(&path, &[ + r##"1"##, + r##"2"##, + r##"
1"##, + r##"
2"##, + ]); + assert_contains_strings(&path, &["strikethrough example"]); + assert_contains_strings( + &path, + &[ + "
  • \nApples", + "
  • \nBroccoli", + "
  • \nCarrots", + ], + ); +} + #[cfg(feature = "search")] mod search { - extern crate serde_json; - use dummy_book::DummyBook; + use crate::dummy_book::DummyBook; use mdbook::utils::fs::file_to_string; use mdbook::MDBook; use std::fs::File; @@ -423,12 +476,13 @@ mod search { fn read_book_index(root: &Path) -> serde_json::Value { let index = root.join("book/searchindex.js"); let index = file_to_string(index).unwrap(); - let index = index.trim_left_matches("window.search = "); - let index = index.trim_right_matches(";"); + let index = index.trim_start_matches("Object.assign(window.search, "); + let index = index.trim_end_matches(");"); serde_json::from_str(&index).unwrap() } #[test] + #[allow(clippy::float_cmp)] fn book_creates_reasonable_search_index() { let temp = DummyBook::new().build().unwrap(); let md = MDBook::load(temp.path()).unwrap(); @@ -457,7 +511,7 @@ mod search { assert_eq!(docs[&some_section]["body"], ""); assert_eq!( docs[&summary]["body"], - "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Nested Chapter Conclusion" + "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Second Chapter Nested Chapter Conclusion" ); assert_eq!(docs[&summary]["breadcrumbs"], "First Chapter » Summary"); assert_eq!(docs[&conclusion]["body"], "I put <HTML> in here!"); diff --git a/vendor/mdbook/tests/searchindex_fixture.json b/vendor/mdbook/tests/searchindex_fixture.json index 78a3915368..824c8473b3 100644 --- a/vendor/mdbook/tests/searchindex_fixture.json +++ b/vendor/mdbook/tests/searchindex_fixture.json @@ -8,6 +8,11 @@ "first/nested.html#some-section", "first/includes.html#includes", "first/includes.html#summary", + "first/markdown.html#markdown-tests", + "first/markdown.html#tables", + "first/markdown.html#footnotes", + "first/markdown.html#strikethrough", + "first/markdown.html#tasklisks", "second.html#second-chapter", "second/nested.html#testing-relative-links-for-the-print-page", "conclusion.html#conclusion" @@ -26,6 +31,31 @@ "title": 1 }, "10": { + "body": 12, + "breadcrumbs": 3, + "title": 1 + }, + "11": { + "body": 2, + "breadcrumbs": 3, + "title": 1 + }, + "12": { + "body": 3, + "breadcrumbs": 3, + "title": 1 + }, + "13": { + "body": 20, + "breadcrumbs": 2, + "title": 2 + }, + "14": { + "body": 13, + "breadcrumbs": 7, + "title": 5 + }, + "15": { "body": 3, "breadcrumbs": 1, "title": 1 @@ -46,7 +76,7 @@ "title": 2 }, "5": { - "body": 0, + "body": 1, "breadcrumbs": 3, "title": 1 }, @@ -56,19 +86,19 @@ "title": 1 }, "7": { - "body": 14, + "body": 15, "breadcrumbs": 3, "title": 1 }, "8": { - "body": 20, - "breadcrumbs": 2, + "body": 3, + "breadcrumbs": 4, "title": 2 }, "9": { - "body": 10, - "breadcrumbs": 7, - "title": 5 + "body": 4, + "breadcrumbs": 3, + "title": 1 } }, "docs": { @@ -85,9 +115,39 @@ "title": "Introduction" }, "10": { + "body": "Footnote example [1] , or with a word [2] . This is a footnote. A longer footnote. With multiple lines. Third line.", + "breadcrumbs": "First Chapter » Footnotes", + "id": "10", + "title": "Footnotes" + }, + "11": { + "body": "strikethrough example", + "breadcrumbs": "First Chapter » Strikethrough", + "id": "11", + "title": "Strikethrough" + }, + "12": { + "body": "Apples Broccoli Carrots", + "breadcrumbs": "First Chapter » Tasklisks", + "id": "12", + "title": "Tasklisks" + }, + "13": { + "body": "This makes sure you can insert runnable Rust files. fn main() { println!(\"Hello World!\");\n#\n# // You can even hide lines! :D\n# println!(\"I am hidden! Expand the code snippet to see me\");\n}", + "breadcrumbs": "Second Chapter", + "id": "13", + "title": "Second Chapter" + }, + "14": { + "body": "When we link to the first section , it should work on both the print page and the non-print page. Link outside . Some image", + "breadcrumbs": "Second Chapter » Testing relative links for the print page", + "id": "14", + "title": "Testing relative links for the print page" + }, + "15": { "body": "I put <HTML> in here!", "breadcrumbs": "Conclusion", - "id": "10", + "id": "15", "title": "Conclusion" }, "2": { @@ -109,7 +169,7 @@ "title": "Nested Chapter" }, "5": { - "body": "", + "body": "assert!(true);", "breadcrumbs": "First Chapter » Some Section", "id": "5", "title": "Some Section" @@ -121,25 +181,25 @@ "title": "Includes" }, "7": { - "body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Nested Chapter Conclusion", + "body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Second Chapter Nested Chapter Conclusion", "breadcrumbs": "First Chapter » Summary", "id": "7", "title": "Summary" }, "8": { - "body": "This makes sure you can insert runnable Rust files. fn main() { println!(\"Hello World!\");\n#\n# // You can even hide lines! :D\n# println!(\"I am hidden! Expand the code snippet to see me\");\n}", - "breadcrumbs": "Second Chapter", + "body": "Tests for some markdown output.", + "breadcrumbs": "First Chapter » Markdown tests", "id": "8", - "title": "Second Chapter" + "title": "Markdown tests" }, "9": { - "body": "When we link to the first section , it should work on both the print page and the non-print page.", - "breadcrumbs": "Second Chapter » Testing relative links for the print page", + "body": "foo bar baz bim", + "breadcrumbs": "First Chapter » Tables", "id": "9", - "title": "Testing relative links for the print page" + "title": "Tables" } }, - "length": 11, + "length": 16, "save": true }, "fields": [ @@ -150,9 +210,41 @@ "index": { "body": { "root": { + "1": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, + "2": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, "a": { "df": 0, "docs": {}, + "p": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + }, "s": { "df": 0, "docs": {}, @@ -177,10 +269,13 @@ "df": 0, "docs": {}, "u": { - "df": 1, + "df": 2, "docs": { "4": { "tf": 1.0 + }, + "5": { + "tf": 1.0 } } } @@ -199,8 +294,40 @@ } }, "b": { + "a": { + "df": 0, + "docs": {}, + "r": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + }, + "z": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + }, "df": 0, "docs": {}, + "i": { + "df": 0, + "docs": {}, + "m": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + }, "o": { "df": 0, "docs": {}, @@ -225,18 +352,70 @@ "h": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } } } + }, + "r": { + "df": 0, + "docs": {}, + "o": { + "c": { + "c": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "l": { + "df": 0, + "docs": {}, + "i": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + } + }, + "df": 0, + "docs": {} + }, + "df": 0, + "docs": {} + } } }, "c": { "a": { "df": 0, "docs": {}, + "r": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + } + }, "u": { "df": 0, "docs": {}, @@ -268,6 +447,9 @@ "r": { "df": 4, "docs": { + "13": { + "tf": 1.0 + }, "2": { "tf": 1.0 }, @@ -276,9 +458,6 @@ }, "7": { "tf": 2.0 - }, - "8": { - "tf": 1.0 } } } @@ -296,10 +475,10 @@ "e": { "df": 2, "docs": { - "4": { + "13": { "tf": 1.0 }, - "8": { + "4": { "tf": 1.0 } } @@ -320,7 +499,7 @@ "s": { "df": 2, "docs": { - "10": { + "15": { "tf": 1.0 }, "7": { @@ -339,7 +518,7 @@ "d": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } }, @@ -381,7 +560,7 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -389,6 +568,29 @@ } }, "x": { + "a": { + "df": 0, + "docs": {}, + "m": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "l": { + "df": 2, + "docs": { + "10": { + "tf": 1.0 + }, + "11": { + "tf": 1.0 + } + } + } + } + } + }, "df": 0, "docs": {}, "p": { @@ -399,7 +601,7 @@ "d": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -428,10 +630,10 @@ "0": { "tf": 1.0 }, - "4": { + "13": { "tf": 1.0 }, - "8": { + "4": { "tf": 1.0 } } @@ -446,13 +648,13 @@ "t": { "df": 3, "docs": { - "2": { + "14": { "tf": 1.0 }, - "7": { + "2": { "tf": 1.0 }, - "9": { + "7": { "tf": 1.0 } } @@ -463,10 +665,42 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } + }, + "o": { + "df": 0, + "docs": {}, + "o": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + }, + "t": { + "df": 0, + "docs": {}, + "n": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "10": { + "tf": 2.0 + } + } + } + } + } + } + } } }, "g": { @@ -512,7 +746,7 @@ "0": { "tf": 1.0 }, - "10": { + "15": { "tf": 1.0 } } @@ -530,7 +764,7 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -542,7 +776,7 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -555,6 +789,22 @@ "i": { "df": 0, "docs": {}, + "m": { + "a": { + "df": 0, + "docs": {}, + "g": { + "df": 1, + "docs": { + "14": { + "tf": 1.0 + } + } + } + }, + "df": 0, + "docs": {} + }, "n": { "c": { "df": 0, @@ -609,7 +859,7 @@ "t": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -704,9 +954,12 @@ "df": 0, "docs": {}, "e": { - "df": 1, + "df": 2, "docs": { - "8": { + "10": { + "tf": 1.4142135623730951 + }, + "13": { "tf": 1.0 } } @@ -714,17 +967,41 @@ "k": { "df": 1, "docs": { - "9": { - "tf": 1.4142135623730951 + "14": { + "tf": 1.7320508075688772 } } } } }, - "t": { - ";": { - "df": 0, - "docs": {}, + "o": { + "df": 0, + "docs": {}, + "n": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "r": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + } + } + } + } + }, + "t": { + ";": { + "df": 0, + "docs": {}, "h": { "df": 0, "docs": {}, @@ -744,7 +1021,7 @@ "t": { "df": 1, "docs": { - "10": { + "15": { "tf": 1.0 } } @@ -772,7 +1049,7 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -784,11 +1061,42 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } } + }, + "r": { + "df": 0, + "docs": {}, + "k": { + "d": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "w": { + "df": 0, + "docs": {}, + "n": { + "df": 2, + "docs": { + "7": { + "tf": 1.0 + }, + "8": { + "tf": 1.4142135623730951 + } + } + } + } + } + }, + "df": 0, + "docs": {} + } } }, "df": 0, @@ -808,6 +1116,34 @@ } } } + }, + "u": { + "df": 0, + "docs": {}, + "l": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + } + } + } + } + } } }, "n": { @@ -838,13 +1174,57 @@ "n": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } } } }, + "o": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "8": { + "tf": 1.0 + } + } + } + } + }, + "s": { + "df": 0, + "docs": {}, + "i": { + "d": { + "df": 1, + "docs": { + "14": { + "tf": 1.0 + } + } + }, + "df": 0, + "docs": {} + } + } + } + } + }, "p": { "a": { "df": 0, @@ -855,7 +1235,7 @@ "e": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.7320508075688772 } } @@ -936,7 +1316,7 @@ "t": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.7320508075688772 } }, @@ -964,7 +1344,7 @@ "o": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -976,7 +1356,7 @@ "i": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1002,7 +1382,7 @@ "t": { "df": 1, "docs": { - "10": { + "15": { "tf": 1.0 } } @@ -1038,7 +1418,7 @@ "l": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } @@ -1062,7 +1442,7 @@ "l": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1081,7 +1461,7 @@ "t": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1103,10 +1483,10 @@ "d": { "df": 2, "docs": { - "7": { + "13": { "tf": 1.0 }, - "8": { + "7": { "tf": 1.0 } } @@ -1127,13 +1507,13 @@ "n": { "df": 3, "docs": { - "3": { + "14": { "tf": 1.0 }, - "5": { + "3": { "tf": 1.0 }, - "9": { + "5": { "tf": 1.0 } } @@ -1147,7 +1527,7 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1171,7 +1551,7 @@ "t": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1181,6 +1561,58 @@ } } }, + "t": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "k": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "h": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "h": { + "df": 1, + "docs": { + "11": { + "tf": 1.4142135623730951 + } + } + } + } + } + } + } + } + } + } + } + } + } + }, "u": { "df": 0, "docs": {}, @@ -1214,7 +1646,7 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1223,6 +1655,50 @@ } }, "t": { + "a": { + "b": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + }, + "df": 0, + "docs": {}, + "s": { + "df": 0, + "docs": {}, + "k": { + "df": 0, + "docs": {}, + "l": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "s": { + "df": 0, + "docs": {}, + "k": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + } + } + } + } + }, "df": 0, "docs": {}, "e": { @@ -1248,10 +1724,13 @@ "df": 0, "docs": {} }, - "df": 1, + "df": 2, "docs": { - "9": { + "14": { "tf": 1.0 + }, + "8": { + "tf": 1.4142135623730951 } } } @@ -1271,6 +1750,26 @@ } } } + }, + "h": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "r": { + "d": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, + "df": 0, + "docs": {} + } + } } }, "w": { @@ -1280,12 +1779,20 @@ "df": 0, "docs": {}, "r": { + "d": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, "df": 0, "docs": {}, "k": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } @@ -1294,7 +1801,7 @@ "d": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1309,9 +1816,41 @@ }, "breadcrumbs": { "root": { + "1": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, + "2": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, "a": { "df": 0, "docs": {}, + "p": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + }, "s": { "df": 0, "docs": {}, @@ -1336,10 +1875,13 @@ "df": 0, "docs": {}, "u": { - "df": 1, + "df": 2, "docs": { "4": { "tf": 1.0 + }, + "5": { + "tf": 1.0 } } } @@ -1358,8 +1900,40 @@ } }, "b": { + "a": { + "df": 0, + "docs": {}, + "r": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + }, + "z": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + }, "df": 0, "docs": {}, + "i": { + "df": 0, + "docs": {}, + "m": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + }, "o": { "df": 0, "docs": {}, @@ -1384,18 +1958,70 @@ "h": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } } } + }, + "r": { + "df": 0, + "docs": {}, + "o": { + "c": { + "c": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "l": { + "df": 0, + "docs": {}, + "i": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + } + }, + "df": 0, + "docs": {} + }, + "df": 0, + "docs": {} + } } }, "c": { "a": { "df": 0, "docs": {}, + "r": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + } + }, "u": { "df": 0, "docs": {}, @@ -1425,8 +2051,23 @@ "df": 0, "docs": {}, "r": { - "df": 7, + "df": 12, "docs": { + "10": { + "tf": 1.0 + }, + "11": { + "tf": 1.0 + }, + "12": { + "tf": 1.0 + }, + "13": { + "tf": 1.4142135623730951 + }, + "14": { + "tf": 1.0 + }, "2": { "tf": 1.4142135623730951 }, @@ -1443,7 +2084,7 @@ "tf": 2.23606797749979 }, "8": { - "tf": 1.4142135623730951 + "tf": 1.0 }, "9": { "tf": 1.0 @@ -1464,10 +2105,10 @@ "e": { "df": 2, "docs": { - "4": { + "13": { "tf": 1.0 }, - "8": { + "4": { "tf": 1.0 } } @@ -1488,7 +2129,7 @@ "s": { "df": 2, "docs": { - "10": { + "15": { "tf": 1.4142135623730951 }, "7": { @@ -1507,7 +2148,7 @@ "d": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } }, @@ -1549,7 +2190,7 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1557,6 +2198,29 @@ } }, "x": { + "a": { + "df": 0, + "docs": {}, + "m": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "l": { + "df": 2, + "docs": { + "10": { + "tf": 1.0 + }, + "11": { + "tf": 1.0 + } + } + } + } + } + }, "df": 0, "docs": {}, "p": { @@ -1567,7 +2231,7 @@ "d": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1596,10 +2260,10 @@ "0": { "tf": 1.0 }, - "4": { + "13": { "tf": 1.0 }, - "8": { + "4": { "tf": 1.0 } } @@ -1612,8 +2276,20 @@ "df": 0, "docs": {}, "t": { - "df": 6, + "df": 11, "docs": { + "10": { + "tf": 1.0 + }, + "11": { + "tf": 1.0 + }, + "12": { + "tf": 1.0 + }, + "14": { + "tf": 1.0 + }, "2": { "tf": 1.4142135623730951 }, @@ -1629,6 +2305,9 @@ "7": { "tf": 1.4142135623730951 }, + "8": { + "tf": 1.0 + }, "9": { "tf": 1.0 } @@ -1640,10 +2319,42 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } + }, + "o": { + "df": 0, + "docs": {}, + "o": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + }, + "t": { + "df": 0, + "docs": {}, + "n": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "10": { + "tf": 2.23606797749979 + } + } + } + } + } + } + } } }, "g": { @@ -1689,7 +2400,7 @@ "0": { "tf": 1.0 }, - "10": { + "15": { "tf": 1.0 } } @@ -1707,7 +2418,7 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1719,7 +2430,7 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1732,6 +2443,22 @@ "i": { "df": 0, "docs": {}, + "m": { + "a": { + "df": 0, + "docs": {}, + "g": { + "df": 1, + "docs": { + "14": { + "tf": 1.0 + } + } + } + }, + "df": 0, + "docs": {} + }, "n": { "c": { "df": 0, @@ -1786,7 +2513,7 @@ "t": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1881,9 +2608,12 @@ "df": 0, "docs": {}, "e": { - "df": 1, + "df": 2, "docs": { - "8": { + "10": { + "tf": 1.4142135623730951 + }, + "13": { "tf": 1.0 } } @@ -1891,8 +2621,32 @@ "k": { "df": 1, "docs": { - "9": { - "tf": 1.7320508075688772 + "14": { + "tf": 2.0 + } + } + } + } + }, + "o": { + "df": 0, + "docs": {}, + "n": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "r": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } } } } @@ -1921,7 +2675,7 @@ "t": { "df": 1, "docs": { - "10": { + "15": { "tf": 1.0 } } @@ -1949,7 +2703,7 @@ "n": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -1961,30 +2715,89 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } } - } - }, - "df": 0, - "docs": {}, - "o": { - "df": 0, - "docs": {}, + }, "r": { "df": 0, "docs": {}, - "e": { - "df": 1, - "docs": { - "2": { + "k": { + "d": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "w": { + "df": 0, + "docs": {}, + "n": { + "df": 2, + "docs": { + "7": { + "tf": 1.0 + }, + "8": { + "tf": 1.7320508075688772 + } + } + } + } + } + }, + "df": 0, + "docs": {} + } + } + }, + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "e": { + "df": 1, + "docs": { + "2": { "tf": 1.0 } } } } + }, + "u": { + "df": 0, + "docs": {}, + "l": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + } + } + } + } + } } }, "n": { @@ -2015,13 +2828,57 @@ "n": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } } } }, + "o": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "p": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "8": { + "tf": 1.0 + } + } + } + } + }, + "s": { + "df": 0, + "docs": {}, + "i": { + "d": { + "df": 1, + "docs": { + "14": { + "tf": 1.0 + } + } + }, + "df": 0, + "docs": {} + } + } + } + } + }, "p": { "a": { "df": 0, @@ -2032,7 +2889,7 @@ "e": { "df": 1, "docs": { - "9": { + "14": { "tf": 2.0 } } @@ -2113,7 +2970,7 @@ "t": { "df": 1, "docs": { - "9": { + "14": { "tf": 2.0 } }, @@ -2141,7 +2998,7 @@ "o": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2153,7 +3010,7 @@ "i": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2179,7 +3036,7 @@ "t": { "df": 1, "docs": { - "10": { + "15": { "tf": 1.0 } } @@ -2215,7 +3072,7 @@ "l": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.4142135623730951 } } @@ -2239,7 +3096,7 @@ "l": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2258,7 +3115,7 @@ "t": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2280,13 +3137,13 @@ "d": { "df": 3, "docs": { - "7": { - "tf": 1.0 - }, - "8": { + "13": { "tf": 1.4142135623730951 }, - "9": { + "14": { + "tf": 1.0 + }, + "7": { "tf": 1.0 } } @@ -2307,14 +3164,14 @@ "n": { "df": 3, "docs": { + "14": { + "tf": 1.0 + }, "3": { "tf": 1.4142135623730951 }, "5": { "tf": 1.4142135623730951 - }, - "9": { - "tf": 1.0 } } } @@ -2327,7 +3184,7 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2351,7 +3208,7 @@ "t": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2361,6 +3218,58 @@ } } }, + "t": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "k": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "h": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "h": { + "df": 1, + "docs": { + "11": { + "tf": 1.7320508075688772 + } + } + } + } + } + } + } + } + } + } + } + } + } + }, "u": { "df": 0, "docs": {}, @@ -2394,7 +3303,7 @@ "e": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2403,6 +3312,50 @@ } }, "t": { + "a": { + "b": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "9": { + "tf": 1.4142135623730951 + } + } + } + }, + "df": 0, + "docs": {}, + "s": { + "df": 0, + "docs": {}, + "k": { + "df": 0, + "docs": {}, + "l": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "s": { + "df": 0, + "docs": {}, + "k": { + "df": 1, + "docs": { + "12": { + "tf": 1.4142135623730951 + } + } + } + } + } + } + } + } + }, "df": 0, "docs": {}, "e": { @@ -2428,10 +3381,13 @@ "df": 0, "docs": {} }, - "df": 1, + "df": 2, "docs": { - "9": { + "14": { "tf": 1.4142135623730951 + }, + "8": { + "tf": 1.7320508075688772 } } } @@ -2451,6 +3407,26 @@ } } } + }, + "h": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "r": { + "d": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, + "df": 0, + "docs": {} + } + } } }, "w": { @@ -2460,12 +3436,20 @@ "df": 0, "docs": {}, "r": { + "d": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + }, "df": 0, "docs": {}, "k": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } @@ -2474,7 +3458,7 @@ "d": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2528,13 +3512,13 @@ "r": { "df": 3, "docs": { - "2": { + "13": { "tf": 1.0 }, - "4": { + "2": { "tf": 1.0 }, - "8": { + "4": { "tf": 1.0 } } @@ -2562,7 +3546,7 @@ "s": { "df": 1, "docs": { - "10": { + "15": { "tf": 1.0 } } @@ -2623,6 +3607,34 @@ } } } + }, + "o": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "n": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "10": { + "tf": 1.0 + } + } + } + } + } + } + } } }, "i": { @@ -2697,7 +3709,7 @@ "k": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } @@ -2705,6 +3717,42 @@ } } }, + "m": { + "a": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "k": { + "d": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "w": { + "df": 0, + "docs": {}, + "n": { + "df": 1, + "docs": { + "8": { + "tf": 1.0 + } + } + } + } + } + }, + "df": 0, + "docs": {} + } + } + }, + "df": 0, + "docs": {} + }, "n": { "df": 0, "docs": {}, @@ -2735,7 +3783,7 @@ "e": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } @@ -2756,7 +3804,7 @@ "t": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } @@ -2774,7 +3822,7 @@ "l": { "df": 1, "docs": { - "9": { + "14": { "tf": 1.0 } } @@ -2795,7 +3843,7 @@ "d": { "df": 1, "docs": { - "8": { + "13": { "tf": 1.0 } } @@ -2831,6 +3879,58 @@ "df": 0, "docs": {} }, + "t": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "k": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "t": { + "df": 0, + "docs": {}, + "h": { + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "o": { + "df": 0, + "docs": {}, + "u": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "h": { + "df": 1, + "docs": { + "11": { + "tf": 1.0 + } + } + } + } + } + } + } + } + } + } + } + } + } + }, "u": { "df": 0, "docs": {}, @@ -2861,6 +3961,50 @@ } }, "t": { + "a": { + "b": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + }, + "df": 0, + "docs": {}, + "s": { + "df": 0, + "docs": {}, + "k": { + "df": 0, + "docs": {}, + "l": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "s": { + "df": 0, + "docs": {}, + "k": { + "df": 1, + "docs": { + "12": { + "tf": 1.0 + } + } + } + } + } + } + } + } + }, "df": 0, "docs": {}, "e": { @@ -2870,9 +4014,12 @@ "df": 0, "docs": {}, "t": { - "df": 1, + "df": 2, "docs": { - "9": { + "14": { + "tf": 1.0 + }, + "8": { "tf": 1.0 } } diff --git a/vendor/mdbook/tests/testing.rs b/vendor/mdbook/tests/testing.rs index 23e1737194..92f9b7e1f8 100644 --- a/vendor/mdbook/tests/testing.rs +++ b/vendor/mdbook/tests/testing.rs @@ -1,8 +1,6 @@ -extern crate mdbook; - mod dummy_book; -use dummy_book::DummyBook; +use crate::dummy_book::DummyBook; use mdbook::MDBook; diff --git a/vendor/new_debug_unreachable/.cargo-checksum.json b/vendor/new_debug_unreachable/.cargo-checksum.json index 9b19767db6..2010c33313 100644 --- a/vendor/new_debug_unreachable/.cargo-checksum.json +++ b/vendor/new_debug_unreachable/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"4081c443d3318411bec6bf1dd8284b7ef4eb39994ca2be66292f0bce6ffae9f6","LICENSE-MIT":"f7715d38a3fa1b4ac97c5729740752505a39cb92ee83ab5b102aeb5eaa7cdea4","README.md":"36ffe300159d4ce4c8224969723606312770117a0a25fbcb3534922c8248b0e9","examples/simple.rs":"c05b124bdad67bfe9e48998bff6a7c6a8789e7f7c9fb3f318f8028a68ef944ed","src/lib.rs":"08a58847b86729b9b2a4eb1125457fc5e76206f9f86a014c1ba26ce6e3f0ebac","tests/check.rs":"ac8691f78269e1cb0cd010150e707f5ea5df14055883f0ee5a5b55a686c5b8de"},"package":"0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"} \ No newline at end of file +{"files":{"Cargo.toml":"a3729c076249f7aafb23435831f077f83625c1a641bdf406987e61b7aa5f968f","LICENSE-MIT":"f7715d38a3fa1b4ac97c5729740752505a39cb92ee83ab5b102aeb5eaa7cdea4","README.md":"4ddc1f5f8cbff9bf2a69dc6ebc07f9518e0315add64fd4c5a1aa4738db655fd9","examples/simple.rs":"c05b124bdad67bfe9e48998bff6a7c6a8789e7f7c9fb3f318f8028a68ef944ed","src/lib.rs":"4b659a21a8c732c49448971b718e7ae4243f706c0607a6a83b9b8c9b1ce89010","tests/check.rs":"ac8691f78269e1cb0cd010150e707f5ea5df14055883f0ee5a5b55a686c5b8de"},"package":"f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"} \ No newline at end of file diff --git a/vendor/new_debug_unreachable/Cargo.toml b/vendor/new_debug_unreachable/Cargo.toml index 47473eec48..cf77c56db3 100644 --- a/vendor/new_debug_unreachable/Cargo.toml +++ b/vendor/new_debug_unreachable/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "new_debug_unreachable" -version = "1.0.1" +version = "1.0.3" authors = ["Matt Brubeck ", "Jonathan Reem "] description = "panic in debug, intrinsics::unreachable() in release (fork of debug_unreachable)" documentation = "https://docs.rs/new_debug_unreachable" @@ -23,5 +23,3 @@ repository = "https://github.com/mbrubeck/rust-debug-unreachable" [lib] name = "debug_unreachable" path = "src/lib.rs" -[dependencies.unreachable] -version = "1.0" diff --git a/vendor/new_debug_unreachable/README.md b/vendor/new_debug_unreachable/README.md index 28ff761b14..58902b2dc4 100644 --- a/vendor/new_debug_unreachable/README.md +++ b/vendor/new_debug_unreachable/README.md @@ -16,6 +16,13 @@ with the rest of your dependencies: new_debug_unreachable = "1.0" ``` +In your Rust code, the library name is still `debug_unreachable`: + +```rust +#[macro_use] +extern crate debug_unreachable; +``` + ## Author [Jonathan Reem](https://medium.com/@jreem) is the original author of debug-unreachable. diff --git a/vendor/new_debug_unreachable/src/lib.rs b/vendor/new_debug_unreachable/src/lib.rs index ebe89ef925..f885c08381 100644 --- a/vendor/new_debug_unreachable/src/lib.rs +++ b/vendor/new_debug_unreachable/src/lib.rs @@ -4,10 +4,7 @@ //! `panic!()` in debug builds, optimization hint in release. -extern crate unreachable; - -#[doc(hidden)] -pub use unreachable::unreachable as __unreachable; +#[doc(hidden)] pub mod _internal { pub use core::hint::unreachable_unchecked; } #[macro_export] /// `panic!()` in debug builds, optimization hint in release. @@ -15,9 +12,9 @@ macro_rules! debug_unreachable { () => { debug_unreachable!("entered unreachable code") }; ($e:expr) => { if cfg!(debug_assertions) { - panic!($e); + panic!($e) } else { - $crate::__unreachable() + $crate::_internal::unreachable_unchecked() } } } diff --git a/vendor/proc-macro2/.cargo-checksum.json b/vendor/proc-macro2/.cargo-checksum.json index f87951f773..ef6f59c460 100644 --- a/vendor/proc-macro2/.cargo-checksum.json +++ b/vendor/proc-macro2/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"f020c87cba7dd2260861239307b2cb93e16c2bed6e2ef6c9178642b1dfcc43a3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"538fd635d385b6a90ef4cc1e361aad717162a139e932a6192212cad8407aa8e1","build.rs":"7698abdd3087e0f3308916c37ade3349b6b000165186b80913013af18d36ecb6","src/lib.rs":"c5c276236d828189a5151c890a66f2b7d1c02beca98f08f2d9c01166df441eb2","src/stable.rs":"a1f29e850e5fc4c602ee1204847124e266087175695d77ec448016db910acb6b","src/strnom.rs":"807c377bdb49b8b1c67d013089b8ff33fe93ffd3fa36b6440dbb1d6fe8cd9c17","src/unstable.rs":"0b7f86862d8254104330d14837ea6ec89e7b3bf2ffe910b73629269f2bc282de","tests/marker.rs":"0227d07bbc7f2e2ad34662a6acb65668b7dc2f79141c4faa672703a04e27bea0","tests/test.rs":"427821bab498926aa56bfcea7d28c36fb24a7d63d7f59d3e7e097bcfc77fe95b"},"package":"77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"} \ No newline at end of file +{"files":{"Cargo.toml":"8b5f969f3fa1acf284b10c1eca350c563cc62fe0da90d9f1aa09c6ddb4410067","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e7de11d9de411a04366b5ee96ce92216b8f97f3db1728be698f71de5e2f11737","build.rs":"c8339bb526fdc6a0d5bcb2ffbd5bf8c23b6cf1beb247cbfbc7d9e0f783668cb2","src/fallback.rs":"33a562ce167b681ebb8302f61b08aec30816980ea16a5ab29daab70c2208ac5f","src/lib.rs":"9de84db0203e305e027fb90cfdd3f389de5eb07fa89e2d37f786ead0ab18e0c6","src/strnom.rs":"60f5380106dbe568cca7abd09877e133c874fbee95d502e4830425c4613a640d","src/wrapper.rs":"9718c9a9e734a88e58945059805e09db753d711a22fede3efa296ee5fba066a6","tests/marker.rs":"0227d07bbc7f2e2ad34662a6acb65668b7dc2f79141c4faa672703a04e27bea0","tests/test.rs":"eab4362ed56b708e704c099a525db1b97bb06f798b0aa7c1ddef7aaef4c7476b"},"package":"cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"} \ No newline at end of file diff --git a/vendor/proc-macro2/Cargo.toml b/vendor/proc-macro2/Cargo.toml index 778fdb8021..da5378f02b 100644 --- a/vendor/proc-macro2/Cargo.toml +++ b/vendor/proc-macro2/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,7 +12,7 @@ [package] name = "proc-macro2" -version = "0.4.24" +version = "0.4.30" authors = ["Alex Crichton "] build = "build.rs" description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n" @@ -32,7 +32,8 @@ version = "0.6" [features] default = ["proc-macro"] -nightly = ["proc-macro"] +nightly = [] proc-macro = [] +span-locations = [] [badges.travis-ci] repository = "alexcrichton/proc-macro2" diff --git a/vendor/proc-macro2/README.md b/vendor/proc-macro2/README.md index f11c4dca65..67d523dc34 100644 --- a/vendor/proc-macro2/README.md +++ b/vendor/proc-macro2/README.md @@ -1,60 +1,76 @@ # proc-macro2 -[![Build Status](https://api.travis-ci.org/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.org/alexcrichton/proc-macro2) +[![Build Status](https://api.travis-ci.com/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.com/alexcrichton/proc-macro2) [![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2) [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2) -A small shim over the `proc_macro` crate in the compiler intended to multiplex -the stable interface as of 1.15.0 and the interface as of 1.30.0. - -New features added in Rust 1.30.0 include: - -* Span information on tokens -* No need to go in/out through strings -* Structured input/output - -Libraries ported to `proc_macro2` can retain support for older compilers while -continuing to get all the nice benefits of using a 1.30.0+ compiler. +A wrapper around the procedural macro API of the compiler's `proc_macro` crate. +This library serves three purposes: + +- **Bring proc-macro-like functionality to other contexts like build.rs and + main.rs.** Types from `proc_macro` are entirely specific to procedural macros + and cannot ever exist in code outside of a procedural macro. Meanwhile + `proc_macro2` types may exist anywhere including non-macro code. By developing + foundational libraries like [syn] and [quote] against `proc_macro2` rather + than `proc_macro`, the procedural macro ecosystem becomes easily applicable to + many other use cases and we avoid reimplementing non-macro equivalents of + those libraries. + +- **Make procedural macros unit testable.** As a consequence of being specific + to procedural macros, nothing that uses `proc_macro` can be executed from a + unit test. In order for helper libraries or components of a macro to be + testable in isolation, they must be implemented using `proc_macro2`. + +- **Provide the latest and greatest APIs across all compiler versions.** + Procedural macros were first introduced to Rust in 1.15.0 with an extremely + minimal interface. Since then, many improvements have landed to make macros + more flexible and easier to write. This library tracks the procedural macro + API of the most recent stable compiler but employs a polyfill to provide that + API consistently across any compiler since 1.15.0. + +[syn]: https://github.com/dtolnay/syn +[quote]: https://github.com/dtolnay/quote ## Usage -This crate compiles on all 1.15.0+ stable compilers and usage looks like: - ```toml [dependencies] proc-macro2 = "0.4" ``` -followed by +The skeleton of a typical procedural macro typically looks like this: ```rust extern crate proc_macro; -extern crate proc_macro2; #[proc_macro_derive(MyDerive)] pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input: proc_macro2::TokenStream = input.into(); + let input = proc_macro2::TokenStream::from(input); let output: proc_macro2::TokenStream = { /* transform input */ }; - output.into() + proc_macro::TokenStream::from(output) } ``` -The 1.30.0 compiler is automatically detected and its interfaces are used when -available. +If parsing with [Syn], you'll use [`parse_macro_input!`] instead to propagate +parse errors correctly back to the compiler when parsing fails. + +[`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html -## Unstable Features +## Unstable features -`proc-macro2` supports exporting some methods from `proc_macro` which are -currently highly unstable, and are not stabilized in the first pass of -`proc_macro` stabilizations. These features are not exported by default. Minor -versions of `proc-macro2` may make breaking changes to them at any time. +The default feature set of proc-macro2 tracks the most recent stable compiler +API. Functionality in `proc_macro` that is not yet stable is not exposed by +proc-macro2 by default. -To enable these features, the `procmacro2_semver_exempt` config flag must be -passed to rustc. +To opt into the additional APIs available in the most recent nightly compiler, +the `procmacro2_semver_exempt` config flag must be passed to rustc. As usual, we +will polyfill those nightly-only APIs all the way back to Rust 1.15.0. As these +are unstable APIs that track the nightly compiler, minor versions of proc-macro2 +may make breaking changes to them at any time. ``` RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build @@ -64,6 +80,8 @@ Note that this must not only be done for your crate, but for any crate that depends on your crate. This infectious nature is intentional, as it serves as a reminder that you are outside of the normal semver guarantees. +Semver exempt methods are marked as such in the proc-macro2 documentation. + # License This project is licensed under either of @@ -78,5 +96,5 @@ at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. diff --git a/vendor/proc-macro2/build.rs b/vendor/proc-macro2/build.rs index cd6df2379e..187255f2fc 100644 --- a/vendor/proc-macro2/build.rs +++ b/vendor/proc-macro2/build.rs @@ -1,3 +1,44 @@ +// rustc-cfg emitted by the build script: +// +// "u128" +// Include u128 and i128 constructors for proc_macro2::Literal. Enabled on +// any compiler 1.26+. +// +// "use_proc_macro" +// Link to extern crate proc_macro. Available on any compiler and any target +// except wasm32. Requires "proc-macro" Cargo cfg to be enabled (default is +// enabled). On wasm32 we never link to proc_macro even if "proc-macro" cfg +// is enabled. +// +// "wrap_proc_macro" +// Wrap types from libproc_macro rather than polyfilling the whole API. +// Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set, +// because we can't emulate the unstable API without emulating everything +// else. Also enabled unconditionally on nightly, in which case the +// procmacro2_semver_exempt surface area is implemented by using the +// nightly-only proc_macro API. +// +// "slow_extend" +// Fallback when `impl Extend for TokenStream` is not available. These impls +// were added one version later than the rest of the proc_macro token API. +// Enabled on rustc 1.29 only. +// +// "proc_macro_span" +// Enable non-dummy behavior of Span::start and Span::end methods which +// requires an unstable compiler feature. Enabled when building with +// nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable +// features. +// +// "super_unstable" +// Implement the semver exempt API in terms of the nightly-only proc_macro +// API. Enabled when using procmacro2_semver_exempt on a nightly compiler. +// +// "span_locations" +// Provide methods Span::start and Span::end which give the line/column +// location of a token. Enabled by procmacro2_semver_exempt or the +// "span-locations" Cargo cfg. This is behind a cfg because tracking +// location inside spans is a performance hit. + use std::env; use std::process::Command; use std::str; @@ -7,34 +48,47 @@ fn main() { let target = env::var("TARGET").unwrap(); - let minor = match rustc_minor_version() { - Some(n) => n, + let version = match rustc_version() { + Some(version) => version, None => return, }; - if minor >= 26 { + if version.minor >= 26 { println!("cargo:rustc-cfg=u128"); } + let semver_exempt = cfg!(procmacro2_semver_exempt); + if semver_exempt { + // https://github.com/alexcrichton/proc-macro2/issues/147 + println!("cargo:rustc-cfg=procmacro2_semver_exempt"); + } + + if semver_exempt || cfg!(feature = "span-locations") { + println!("cargo:rustc-cfg=span_locations"); + } + if !enable_use_proc_macro(&target) { return; } + println!("cargo:rustc-cfg=use_proc_macro"); // Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate - if (minor >= 29 && !cfg!(procmacro2_semver_exempt)) || cfg!(feature = "nightly") { + if version.nightly || version.minor >= 29 && !semver_exempt { println!("cargo:rustc-cfg=wrap_proc_macro"); - - if cfg!(procmacro2_semver_exempt) { - println!("cargo:rustc-cfg=super_unstable"); - // https://github.com/alexcrichton/proc-macro2/issues/147 - println!("cargo:rustc-cfg=procmacro2_semver_exempt"); - } } - if minor == 29 { + if version.minor == 29 { println!("cargo:rustc-cfg=slow_extend"); } + + if version.nightly && feature_allowed("proc_macro_span") { + println!("cargo:rustc-cfg=proc_macro_span"); + } + + if semver_exempt && version.nightly { + println!("cargo:rustc-cfg=super_unstable"); + } } fn enable_use_proc_macro(target: &str) -> bool { @@ -47,7 +101,12 @@ fn enable_use_proc_macro(target: &str) -> bool { cfg!(feature = "proc-macro") } -fn rustc_minor_version() -> Option { +struct RustcVersion { + minor: u32, + nightly: bool, +} + +fn rustc_version() -> Option { macro_rules! otry { ($e:expr) => { match $e { @@ -56,12 +115,43 @@ fn rustc_minor_version() -> Option { } }; } + let rustc = otry!(env::var_os("RUSTC")); let output = otry!(Command::new(rustc).arg("--version").output().ok()); let version = otry!(str::from_utf8(&output.stdout).ok()); + let nightly = version.contains("nightly"); let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } - otry!(pieces.next()).parse().ok() + let minor = otry!(pieces.next()); + let minor = otry!(minor.parse().ok()); + + Some(RustcVersion { + minor: minor, + nightly: nightly, + }) +} + +fn feature_allowed(feature: &str) -> bool { + // Recognized formats: + // + // -Z allow-features=feature1,feature2 + // + // -Zallow-features=feature1,feature2 + + if let Some(rustflags) = env::var_os("RUSTFLAGS") { + for mut flag in rustflags.to_string_lossy().split(' ') { + if flag.starts_with("-Z") { + flag = &flag["-Z".len()..]; + } + if flag.starts_with("allow-features=") { + flag = &flag["allow-features=".len()..]; + return flag.split(',').any(|allowed| allowed == feature); + } + } + } + + // No allow-features= flag, allowed by default. + true } diff --git a/vendor/proc-macro2/src/stable.rs b/vendor/proc-macro2/src/fallback.rs similarity index 93% rename from vendor/proc-macro2/src/stable.rs rename to vendor/proc-macro2/src/fallback.rs index baeed69af6..f40a874617 100644 --- a/vendor/proc-macro2/src/stable.rs +++ b/vendor/proc-macro2/src/fallback.rs @@ -1,6 +1,4 @@ -#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))] - -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] use std::cell::RefCell; #[cfg(procmacro2_semver_exempt)] use std::cmp; @@ -35,10 +33,10 @@ impl TokenStream { } } -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] fn get_cursor(src: &str) -> Cursor { - // Create a dummy file & add it to the codemap - CODEMAP.with(|cm| { + // Create a dummy file & add it to the source map + SOURCE_MAP.with(|cm| { let mut cm = cm.borrow_mut(); let name = format!("", cm.files.len()); let span = cm.add_file(&name, src); @@ -49,7 +47,7 @@ fn get_cursor(src: &str) -> Cursor { }) } -#[cfg(not(procmacro2_semver_exempt))] +#[cfg(not(span_locations))] fn get_cursor(src: &str) -> Cursor { Cursor { rest: src } } @@ -58,7 +56,7 @@ impl FromStr for TokenStream { type Err = LexError; fn from_str(src: &str) -> Result { - // Create a dummy file & add it to the codemap + // Create a dummy file & add it to the source map let cursor = get_cursor(src); match token_stream(cursor) { @@ -225,27 +223,41 @@ pub struct LineColumn { pub column: usize, } -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] thread_local! { - static CODEMAP: RefCell = RefCell::new(Codemap { + static SOURCE_MAP: RefCell = RefCell::new(SourceMap { // NOTE: We start with a single dummy file which all call_site() and // def_site() spans reference. - files: vec![FileInfo { - name: "".to_owned(), - span: Span { lo: 0, hi: 0 }, - lines: vec![0], + files: vec![{ + #[cfg(procmacro2_semver_exempt)] + { + FileInfo { + name: "".to_owned(), + span: Span { lo: 0, hi: 0 }, + lines: vec![0], + } + } + + #[cfg(not(procmacro2_semver_exempt))] + { + FileInfo { + span: Span { lo: 0, hi: 0 }, + lines: vec![0], + } + } }], }); } -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] struct FileInfo { + #[cfg(procmacro2_semver_exempt)] name: String, span: Span, lines: Vec, } -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] impl FileInfo { fn offset_line_column(&self, offset: usize) -> LineColumn { assert!(self.span_within(Span { @@ -271,7 +283,7 @@ impl FileInfo { } /// Computesthe offsets of each line in the given source string. -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] fn lines_offsets(s: &str) -> Vec { let mut lines = vec![0]; let mut prev = 0; @@ -282,13 +294,13 @@ fn lines_offsets(s: &str) -> Vec { lines } -#[cfg(procmacro2_semver_exempt)] -struct Codemap { +#[cfg(span_locations)] +struct SourceMap { files: Vec, } -#[cfg(procmacro2_semver_exempt)] -impl Codemap { +#[cfg(span_locations)] +impl SourceMap { fn next_start_pos(&self) -> u32 { // Add 1 so there's always space between files. // @@ -306,12 +318,20 @@ impl Codemap { hi: lo + (src.len() as u32), }; + #[cfg(procmacro2_semver_exempt)] self.files.push(FileInfo { name: name.to_owned(), span: span, lines: lines, }); + #[cfg(not(procmacro2_semver_exempt))] + self.files.push(FileInfo { + span: span, + lines: lines, + }); + let _ = name; + span } @@ -327,27 +347,29 @@ impl Codemap { #[derive(Clone, Copy, PartialEq, Eq)] pub struct Span { - #[cfg(procmacro2_semver_exempt)] + #[cfg(span_locations)] lo: u32, - #[cfg(procmacro2_semver_exempt)] + #[cfg(span_locations)] hi: u32, } impl Span { - #[cfg(not(procmacro2_semver_exempt))] + #[cfg(not(span_locations))] pub fn call_site() -> Span { Span {} } - #[cfg(procmacro2_semver_exempt)] + #[cfg(span_locations)] pub fn call_site() -> Span { Span { lo: 0, hi: 0 } } + #[cfg(procmacro2_semver_exempt)] pub fn def_site() -> Span { Span::call_site() } + #[cfg(procmacro2_semver_exempt)] pub fn resolved_at(&self, _other: Span) -> Span { // Stable spans consist only of line/column information, so // `resolved_at` and `located_at` only select which span the @@ -355,13 +377,14 @@ impl Span { *self } + #[cfg(procmacro2_semver_exempt)] pub fn located_at(&self, other: Span) -> Span { other } #[cfg(procmacro2_semver_exempt)] pub fn source_file(&self) -> SourceFile { - CODEMAP.with(|cm| { + SOURCE_MAP.with(|cm| { let cm = cm.borrow(); let fi = cm.fileinfo(*self); SourceFile { @@ -370,18 +393,18 @@ impl Span { }) } - #[cfg(procmacro2_semver_exempt)] + #[cfg(span_locations)] pub fn start(&self) -> LineColumn { - CODEMAP.with(|cm| { + SOURCE_MAP.with(|cm| { let cm = cm.borrow(); let fi = cm.fileinfo(*self); fi.offset_line_column(self.lo as usize) }) } - #[cfg(procmacro2_semver_exempt)] + #[cfg(span_locations)] pub fn end(&self) -> LineColumn { - CODEMAP.with(|cm| { + SOURCE_MAP.with(|cm| { let cm = cm.borrow(); let fi = cm.fileinfo(*self); fi.offset_line_column(self.hi as usize) @@ -390,7 +413,7 @@ impl Span { #[cfg(procmacro2_semver_exempt)] pub fn join(&self, other: Span) -> Option { - CODEMAP.with(|cm| { + SOURCE_MAP.with(|cm| { let cm = cm.borrow(); // If `other` is not within the same FileInfo as us, return None. if !cm.fileinfo(*self).span_within(other) { @@ -414,6 +437,12 @@ impl fmt::Debug for Span { } } +pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { + if cfg!(procmacro2_semver_exempt) { + debug.field("span", &span); + } +} + #[derive(Clone)] pub struct Group { delimiter: Delimiter, @@ -442,10 +471,12 @@ impl Group { self.span } + #[cfg(procmacro2_semver_exempt)] pub fn span_open(&self) -> Span { self.span } + #[cfg(procmacro2_semver_exempt)] pub fn span_close(&self) -> Span { self.span } @@ -492,7 +523,7 @@ pub struct Ident { impl Ident { fn _new(string: &str, raw: bool, span: Span) -> Ident { - validate_term(string); + validate_ident(string); Ident { sym: string.to_owned(), @@ -535,7 +566,7 @@ fn is_ident_continue(c: char) -> bool { || (c > '\x7f' && UnicodeXID::is_xid_continue(c)) } -fn validate_term(string: &str) { +fn validate_ident(string: &str) { let validate = string; if validate.is_empty() { panic!("Ident is not allowed to be empty; use Option"); @@ -703,17 +734,31 @@ impl Literal { } pub fn string(t: &str) -> Literal { - let mut s = t - .chars() - .flat_map(|c| c.escape_default()) - .collect::(); - s.push('"'); - s.insert(0, '"'); - Literal::_new(s) + let mut text = String::with_capacity(t.len() + 2); + text.push('"'); + for c in t.chars() { + if c == '\'' { + // escape_default turns this into "\'" which is unnecessary. + text.push(c); + } else { + text.extend(c.escape_default()); + } + } + text.push('"'); + Literal::_new(text) } pub fn character(t: char) -> Literal { - Literal::_new(format!("'{}'", t.escape_default().collect::())) + let mut text = String::new(); + text.push('\''); + if t == '"' { + // escape_default turns this into '\"' which is unnecessary. + text.push(t); + } else { + text.extend(t.escape_default()); + } + text.push('\''); + Literal::_new(text) } pub fn byte_string(bytes: &[u8]) -> Literal { @@ -782,16 +827,16 @@ fn token_stream(mut input: Cursor) -> PResult { Ok((input, TokenStream { inner: trees })) } -#[cfg(not(procmacro2_semver_exempt))] +#[cfg(not(span_locations))] fn spanned<'a, T>( input: Cursor<'a>, f: fn(Cursor<'a>) -> PResult<'a, T>, ) -> PResult<'a, (T, ::Span)> { let (a, b) = f(skip_whitespace(input))?; - Ok((a, ((b, ::Span::_new_stable(Span {}))))) + Ok((a, ((b, ::Span::_new_stable(Span::call_site()))))) } -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] fn spanned<'a, T>( input: Cursor<'a>, f: fn(Cursor<'a>) -> PResult<'a, T>, diff --git a/vendor/proc-macro2/src/lib.rs b/vendor/proc-macro2/src/lib.rs index db51272275..7181455c85 100644 --- a/vendor/proc-macro2/src/lib.rs +++ b/vendor/proc-macro2/src/lib.rs @@ -1,35 +1,72 @@ -//! A "shim crate" intended to multiplex the [`proc_macro`] API on to stable -//! Rust. +//! A wrapper around the procedural macro API of the compiler's [`proc_macro`] +//! crate. This library serves three purposes: //! -//! Procedural macros in Rust operate over the upstream -//! [`proc_macro::TokenStream`][ts] type. This type currently is quite -//! conservative and exposed no internal implementation details. Nightly -//! compilers, however, contain a much richer interface. This richer interface -//! allows fine-grained inspection of the token stream which avoids -//! stringification/re-lexing and also preserves span information. +//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/ +//! +//! - **Bring proc-macro-like functionality to other contexts like build.rs and +//! main.rs.** Types from `proc_macro` are entirely specific to procedural +//! macros and cannot ever exist in code outside of a procedural macro. +//! Meanwhile `proc_macro2` types may exist anywhere including non-macro code. +//! By developing foundational libraries like [syn] and [quote] against +//! `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem +//! becomes easily applicable to many other use cases and we avoid +//! reimplementing non-macro equivalents of those libraries. +//! +//! - **Make procedural macros unit testable.** As a consequence of being +//! specific to procedural macros, nothing that uses `proc_macro` can be +//! executed from a unit test. In order for helper libraries or components of +//! a macro to be testable in isolation, they must be implemented using +//! `proc_macro2`. +//! +//! - **Provide the latest and greatest APIs across all compiler versions.** +//! Procedural macros were first introduced to Rust in 1.15.0 with an +//! extremely minimal interface. Since then, many improvements have landed to +//! make macros more flexible and easier to write. This library tracks the +//! procedural macro API of the most recent stable compiler but employs a +//! polyfill to provide that API consistently across any compiler since +//! 1.15.0. +//! +//! [syn]: https://github.com/dtolnay/syn +//! [quote]: https://github.com/dtolnay/quote +//! +//! # Usage +//! +//! The skeleton of a typical procedural macro typically looks like this: +//! +//! ```edition2018 +//! extern crate proc_macro; //! -//! The upcoming APIs added to [`proc_macro`] upstream are the foundation for -//! productive procedural macros in the ecosystem. To help prepare the ecosystem -//! for using them this crate serves to both compile on stable and nightly and -//! mirrors the API-to-be. The intention is that procedural macros which switch -//! to use this crate will be trivially able to switch to the upstream -//! `proc_macro` crate once its API stabilizes. +//! # const IGNORE: &str = stringify! { +//! #[proc_macro_derive(MyDerive)] +//! # }; +//! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { +//! let input = proc_macro2::TokenStream::from(input); //! -//! In the meantime this crate also has a `nightly` Cargo feature which -//! enables it to reimplement itself with the unstable API of [`proc_macro`]. -//! This'll allow immediate usage of the beneficial upstream API, particularly -//! around preserving span information. +//! let output: proc_macro2::TokenStream = { +//! /* transform input */ +//! # input +//! }; //! -//! # Unstable Features +//! proc_macro::TokenStream::from(output) +//! } +//! ``` +//! +//! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to +//! propagate parse errors correctly back to the compiler when parsing fails. +//! +//! [`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html +//! +//! # Unstable features //! -//! `proc-macro2` supports exporting some methods from `proc_macro` which are -//! currently highly unstable, and may not be stabilized in the first pass of -//! `proc_macro` stabilizations. These features are not exported by default. -//! Minor versions of `proc-macro2` may make breaking changes to them at any -//! time. +//! The default feature set of proc-macro2 tracks the most recent stable +//! compiler API. Functionality in `proc_macro` that is not yet stable is not +//! exposed by proc-macro2 by default. //! -//! To enable these features, the `procmacro2_semver_exempt` config flag must be -//! passed to rustc. +//! To opt into the additional APIs available in the most recent nightly +//! compiler, the `procmacro2_semver_exempt` config flag must be passed to +//! rustc. As usual, we will polyfill those nightly-only APIs all the way back +//! to Rust 1.15.0. As these are unstable APIs that track the nightly compiler, +//! minor versions of proc-macro2 may make breaking changes to them at any time. //! //! ```sh //! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build @@ -39,15 +76,12 @@ //! depends on your crate. This infectious nature is intentional, as it serves //! as a reminder that you are outside of the normal semver guarantees. //! -//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/ -//! [ts]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html +//! Semver exempt methods are marked as such in the proc-macro2 documentation. // Proc-macro2 types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.24")] -#![cfg_attr( - super_unstable, - feature(proc_macro_raw_ident, proc_macro_span, proc_macro_def_site) -)] +#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.30")] +#![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] +#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))] #[cfg(use_proc_macro)] extern crate proc_macro; @@ -65,11 +99,11 @@ use std::str::FromStr; #[macro_use] mod strnom; -mod stable; +mod fallback; #[cfg(not(wrap_proc_macro))] -use stable as imp; -#[path = "unstable.rs"] +use fallback as imp; +#[path = "wrapper.rs"] #[cfg(wrap_proc_macro)] mod imp; @@ -100,7 +134,7 @@ impl TokenStream { } } - fn _new_stable(inner: stable::TokenStream) -> TokenStream { + fn _new_stable(inner: fallback::TokenStream) -> TokenStream { TokenStream { inner: inner.into(), _marker: marker::PhantomData, @@ -266,7 +300,8 @@ impl fmt::Debug for SourceFile { /// A line-column pair representing the start or end of a `Span`. /// /// This type is semver exempt and not exposed by default. -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct LineColumn { /// The 1-indexed line in the source file on which the span starts or ends /// (inclusive). @@ -291,7 +326,7 @@ impl Span { } } - fn _new_stable(inner: stable::Span) -> Span { + fn _new_stable(inner: fallback::Span) -> Span { Span { inner: inner.into(), _marker: marker::PhantomData, @@ -333,11 +368,26 @@ impl Span { Span::_new(self.inner.located_at(other.inner)) } - /// This method is only available when the `"nightly"` feature is enabled. + /// Convert `proc_macro2::Span` to `proc_macro::Span`. + /// + /// This method is available when building with a nightly compiler, or when + /// building with rustc 1.29+ *without* semver exempt features. + /// + /// # Panics + /// + /// Panics if called from outside of a procedural macro. Unlike + /// `proc_macro2::Span`, the `proc_macro::Span` type can only exist within + /// the context of a procedural macro invocation. + #[cfg(wrap_proc_macro)] + pub fn unwrap(self) -> proc_macro::Span { + self.inner.unwrap() + } + + // Soft deprecated. Please use Span::unwrap. + #[cfg(wrap_proc_macro)] #[doc(hidden)] - #[cfg(any(feature = "nightly", super_unstable))] pub fn unstable(self) -> proc_macro::Span { - self.inner.unstable() + self.unwrap() } /// The original source file into which this span points. @@ -350,8 +400,8 @@ impl Span { /// Get the starting line/column in the source file for this span. /// - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] + /// This method requires the `"span-locations"` feature to be enabled. + #[cfg(span_locations)] pub fn start(&self) -> LineColumn { let imp::LineColumn { line, column } = self.inner.start(); LineColumn { @@ -362,8 +412,8 @@ impl Span { /// Get the ending line/column in the source file for this span. /// - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] + /// This method requires the `"span-locations"` feature to be enabled. + #[cfg(span_locations)] pub fn end(&self) -> LineColumn { let imp::LineColumn { line, column } = self.inner.end(); LineColumn { @@ -487,8 +537,7 @@ impl fmt::Debug for TokenTree { TokenTree::Ident(ref t) => { let mut debug = f.debug_struct("Ident"); debug.field("sym", &format_args!("{}", t)); - #[cfg(any(feature = "nightly", procmacro2_semver_exempt))] - debug.field("span", &t.span()); + imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner); debug.finish() } TokenTree::Punct(ref t) => t.fmt(f), @@ -527,12 +576,10 @@ pub enum Delimiter { impl Group { fn _new(inner: imp::Group) -> Self { - Group { - inner: inner, - } + Group { inner: inner } } - fn _new_stable(inner: stable::Group) -> Self { + fn _new_stable(inner: fallback::Group) -> Self { Group { inner: inner.into(), } @@ -699,8 +746,7 @@ impl fmt::Debug for Punct { let mut debug = fmt.debug_struct("Punct"); debug.field("op", &self.op); debug.field("spacing", &self.spacing); - #[cfg(procmacro2_semver_exempt)] - debug.field("span", &self.span); + imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner); debug.finish() } } @@ -727,9 +773,7 @@ impl fmt::Debug for Punct { /// A span must be provided explicitly which governs the name resolution /// behavior of the resulting identifier. /// -/// ```rust -/// extern crate proc_macro2; -/// +/// ```edition2018 /// use proc_macro2::{Ident, Span}; /// /// fn main() { @@ -741,13 +785,9 @@ impl fmt::Debug for Punct { /// /// An ident can be interpolated into a token stream using the `quote!` macro. /// -/// ```rust -/// #[macro_use] -/// extern crate quote; -/// -/// extern crate proc_macro2; -/// +/// ```edition2018 /// use proc_macro2::{Ident, Span}; +/// use quote::quote; /// /// fn main() { /// let ident = Ident::new("demo", Span::call_site()); @@ -764,9 +804,7 @@ impl fmt::Debug for Punct { /// A string representation of the ident is available through the `to_string()` /// method. /// -/// ```rust -/// # extern crate proc_macro2; -/// # +/// ```edition2018 /// # use proc_macro2::{Ident, Span}; /// # /// # let ident = Ident::new("another_identifier", Span::call_site()); @@ -816,7 +854,12 @@ impl Ident { /// # Panics /// /// Panics if the input string is neither a keyword nor a legal variable - /// name. + /// name. If you are not sure whether the string contains an identifier and + /// need to handle an error case, use + /// syn::parse_str::<Ident> + /// rather than `Ident::new`. pub fn new(string: &str, span: Span) -> Ident { Ident::_new(imp::Ident::new(string, span.inner)) } @@ -954,7 +997,7 @@ impl Literal { } } - fn _new_stable(inner: stable::Literal) -> Literal { + fn _new_stable(inner: fallback::Literal) -> Literal { Literal { inner: inner.into(), _marker: marker::PhantomData, @@ -1079,6 +1122,7 @@ pub mod token_stream { /// /// The iteration is "shallow", e.g. the iterator doesn't recurse into /// delimited groups, and returns whole groups as token trees. + #[derive(Clone)] pub struct IntoIter { inner: imp::TokenTreeIter, _marker: marker::PhantomData>, diff --git a/vendor/proc-macro2/src/strnom.rs b/vendor/proc-macro2/src/strnom.rs index 099dab9228..96789d5691 100644 --- a/vendor/proc-macro2/src/strnom.rs +++ b/vendor/proc-macro2/src/strnom.rs @@ -4,23 +4,23 @@ use std::str::{Bytes, CharIndices, Chars}; use unicode_xid::UnicodeXID; -use stable::LexError; +use fallback::LexError; #[derive(Copy, Clone, Eq, PartialEq)] pub struct Cursor<'a> { pub rest: &'a str, - #[cfg(procmacro2_semver_exempt)] + #[cfg(span_locations)] pub off: u32, } impl<'a> Cursor<'a> { - #[cfg(not(procmacro2_semver_exempt))] + #[cfg(not(span_locations))] pub fn advance(&self, amt: usize) -> Cursor<'a> { Cursor { rest: &self.rest[amt..], } } - #[cfg(procmacro2_semver_exempt)] + #[cfg(span_locations)] pub fn advance(&self, amt: usize) -> Cursor<'a> { Cursor { rest: &self.rest[amt..], diff --git a/vendor/proc-macro2/src/unstable.rs b/vendor/proc-macro2/src/wrapper.rs similarity index 58% rename from vendor/proc-macro2/src/unstable.rs rename to vendor/proc-macro2/src/wrapper.rs index c4cf11a8da..994ed24d88 100644 --- a/vendor/proc-macro2/src/unstable.rs +++ b/vendor/proc-macro2/src/wrapper.rs @@ -1,5 +1,3 @@ -#![cfg_attr(not(super_unstable), allow(dead_code))] - use std::fmt; use std::iter; use std::panic::{self, PanicInfo}; @@ -7,26 +5,27 @@ use std::panic::{self, PanicInfo}; use std::path::PathBuf; use std::str::FromStr; +use fallback; use proc_macro; -use stable; use {Delimiter, Punct, Spacing, TokenTree}; #[derive(Clone)] pub enum TokenStream { - Nightly(proc_macro::TokenStream), - Stable(stable::TokenStream), + Compiler(proc_macro::TokenStream), + Fallback(fallback::TokenStream), } pub enum LexError { - Nightly(proc_macro::LexError), - Stable(stable::LexError), + Compiler(proc_macro::LexError), + Fallback(fallback::LexError), } fn nightly_works() -> bool { use std::sync::atomic::*; use std::sync::Once; + #[allow(deprecated)] static WORKS: AtomicUsize = ATOMIC_USIZE_INIT; static INIT: Once = Once::new(); @@ -87,30 +86,30 @@ fn mismatch() -> ! { impl TokenStream { pub fn new() -> TokenStream { if nightly_works() { - TokenStream::Nightly(proc_macro::TokenStream::new()) + TokenStream::Compiler(proc_macro::TokenStream::new()) } else { - TokenStream::Stable(stable::TokenStream::new()) + TokenStream::Fallback(fallback::TokenStream::new()) } } pub fn is_empty(&self) -> bool { match self { - TokenStream::Nightly(tts) => tts.is_empty(), - TokenStream::Stable(tts) => tts.is_empty(), + TokenStream::Compiler(tts) => tts.is_empty(), + TokenStream::Fallback(tts) => tts.is_empty(), } } fn unwrap_nightly(self) -> proc_macro::TokenStream { match self { - TokenStream::Nightly(s) => s, - TokenStream::Stable(_) => mismatch(), + TokenStream::Compiler(s) => s, + TokenStream::Fallback(_) => mismatch(), } } - fn unwrap_stable(self) -> stable::TokenStream { + fn unwrap_stable(self) -> fallback::TokenStream { match self { - TokenStream::Nightly(_) => mismatch(), - TokenStream::Stable(s) => s, + TokenStream::Compiler(_) => mismatch(), + TokenStream::Fallback(s) => s, } } } @@ -120,9 +119,9 @@ impl FromStr for TokenStream { fn from_str(src: &str) -> Result { if nightly_works() { - Ok(TokenStream::Nightly(src.parse()?)) + Ok(TokenStream::Compiler(src.parse()?)) } else { - Ok(TokenStream::Stable(src.parse()?)) + Ok(TokenStream::Fallback(src.parse()?)) } } } @@ -130,37 +129,37 @@ impl FromStr for TokenStream { impl fmt::Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - TokenStream::Nightly(tts) => tts.fmt(f), - TokenStream::Stable(tts) => tts.fmt(f), + TokenStream::Compiler(tts) => tts.fmt(f), + TokenStream::Fallback(tts) => tts.fmt(f), } } } impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> TokenStream { - TokenStream::Nightly(inner) + TokenStream::Compiler(inner) } } impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> proc_macro::TokenStream { match inner { - TokenStream::Nightly(inner) => inner, - TokenStream::Stable(inner) => inner.to_string().parse().unwrap(), + TokenStream::Compiler(inner) => inner, + TokenStream::Fallback(inner) => inner.to_string().parse().unwrap(), } } } -impl From for TokenStream { - fn from(inner: stable::TokenStream) -> TokenStream { - TokenStream::Stable(inner) +impl From for TokenStream { + fn from(inner: fallback::TokenStream) -> TokenStream { + TokenStream::Fallback(inner) } } impl From for TokenStream { fn from(token: TokenTree) -> TokenStream { if !nightly_works() { - return TokenStream::Stable(token.into()); + return TokenStream::Fallback(token.into()); } let tt: proc_macro::TokenTree = match token { TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(), @@ -176,7 +175,7 @@ impl From for TokenStream { TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(), TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(), }; - TokenStream::Nightly(tt.into()) + TokenStream::Compiler(tt.into()) } } @@ -187,12 +186,12 @@ impl iter::FromIterator for TokenStream { .into_iter() .map(TokenStream::from) .flat_map(|t| match t { - TokenStream::Nightly(s) => s, - TokenStream::Stable(_) => mismatch(), + TokenStream::Compiler(s) => s, + TokenStream::Fallback(_) => mismatch(), }); - TokenStream::Nightly(trees.collect()) + TokenStream::Compiler(trees.collect()) } else { - TokenStream::Stable(trees.into_iter().collect()) + TokenStream::Fallback(trees.into_iter().collect()) } } } @@ -202,36 +201,31 @@ impl iter::FromIterator for TokenStream { let mut streams = streams.into_iter(); match streams.next() { #[cfg(slow_extend)] - Some(TokenStream::Nightly(first)) => { - let stream = iter::once(first).chain(streams.map(|s| { - match s { - TokenStream::Nightly(s) => s, - TokenStream::Stable(_) => mismatch(), - } - })).collect(); - TokenStream::Nightly(stream) + Some(TokenStream::Compiler(first)) => { + let stream = iter::once(first) + .chain(streams.map(|s| match s { + TokenStream::Compiler(s) => s, + TokenStream::Fallback(_) => mismatch(), + })) + .collect(); + TokenStream::Compiler(stream) } #[cfg(not(slow_extend))] - Some(TokenStream::Nightly(mut first)) => { - first.extend(streams.map(|s| { - match s { - TokenStream::Nightly(s) => s, - TokenStream::Stable(_) => mismatch(), - } + Some(TokenStream::Compiler(mut first)) => { + first.extend(streams.map(|s| match s { + TokenStream::Compiler(s) => s, + TokenStream::Fallback(_) => mismatch(), })); - TokenStream::Nightly(first) + TokenStream::Compiler(first) } - Some(TokenStream::Stable(mut first)) => { - first.extend(streams.map(|s| { - match s { - TokenStream::Stable(s) => s, - TokenStream::Nightly(_) => mismatch(), - } + Some(TokenStream::Fallback(mut first)) => { + first.extend(streams.map(|s| match s { + TokenStream::Fallback(s) => s, + TokenStream::Compiler(_) => mismatch(), })); - TokenStream::Stable(first) + TokenStream::Fallback(first) } None => TokenStream::new(), - } } } @@ -239,7 +233,7 @@ impl iter::FromIterator for TokenStream { impl Extend for TokenStream { fn extend>(&mut self, streams: I) { match self { - TokenStream::Nightly(tts) => { + TokenStream::Compiler(tts) => { #[cfg(not(slow_extend))] { tts.extend( @@ -250,21 +244,19 @@ impl Extend for TokenStream { } #[cfg(slow_extend)] { - *tts = tts - .clone() - .into_iter() - .chain( - streams - .into_iter() - .map(TokenStream::from) - .flat_map(|t| match t { - TokenStream::Nightly(tts) => tts.into_iter(), + *tts = + tts.clone() + .into_iter() + .chain(streams.into_iter().map(TokenStream::from).flat_map( + |t| match t { + TokenStream::Compiler(tts) => tts.into_iter(), _ => mismatch(), - }), - ).collect(); + }, + )) + .collect(); } } - TokenStream::Stable(tts) => tts.extend(streams), + TokenStream::Fallback(tts) => tts.extend(streams), } } } @@ -272,7 +264,7 @@ impl Extend for TokenStream { impl Extend for TokenStream { fn extend>(&mut self, streams: I) { match self { - TokenStream::Nightly(tts) => { + TokenStream::Compiler(tts) => { #[cfg(not(slow_extend))] { tts.extend(streams.into_iter().map(|stream| stream.unwrap_nightly())); @@ -282,17 +274,14 @@ impl Extend for TokenStream { *tts = tts .clone() .into_iter() - .chain( - streams - .into_iter() - .flat_map(|t| match t { - TokenStream::Nightly(tts) => tts.into_iter(), - _ => mismatch(), - }), - ).collect(); + .chain(streams.into_iter().flat_map(|t| match t { + TokenStream::Compiler(tts) => tts.into_iter(), + _ => mismatch(), + })) + .collect(); } } - TokenStream::Stable(tts) => { + TokenStream::Fallback(tts) => { tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable())) } } @@ -302,36 +291,37 @@ impl Extend for TokenStream { impl fmt::Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - TokenStream::Nightly(tts) => tts.fmt(f), - TokenStream::Stable(tts) => tts.fmt(f), + TokenStream::Compiler(tts) => tts.fmt(f), + TokenStream::Fallback(tts) => tts.fmt(f), } } } impl From for LexError { fn from(e: proc_macro::LexError) -> LexError { - LexError::Nightly(e) + LexError::Compiler(e) } } -impl From for LexError { - fn from(e: stable::LexError) -> LexError { - LexError::Stable(e) +impl From for LexError { + fn from(e: fallback::LexError) -> LexError { + LexError::Fallback(e) } } impl fmt::Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - LexError::Nightly(e) => e.fmt(f), - LexError::Stable(e) => e.fmt(f), + LexError::Compiler(e) => e.fmt(f), + LexError::Fallback(e) => e.fmt(f), } } } +#[derive(Clone)] pub enum TokenTreeIter { - Nightly(proc_macro::token_stream::IntoIter), - Stable(stable::TokenTreeIter), + Compiler(proc_macro::token_stream::IntoIter), + Fallback(fallback::TokenTreeIter), } impl IntoIterator for TokenStream { @@ -340,8 +330,8 @@ impl IntoIterator for TokenStream { fn into_iter(self) -> TokenTreeIter { match self { - TokenStream::Nightly(tts) => TokenTreeIter::Nightly(tts.into_iter()), - TokenStream::Stable(tts) => TokenTreeIter::Stable(tts.into_iter()), + TokenStream::Compiler(tts) => TokenTreeIter::Compiler(tts.into_iter()), + TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()), } } } @@ -351,29 +341,29 @@ impl Iterator for TokenTreeIter { fn next(&mut self) -> Option { let token = match self { - TokenTreeIter::Nightly(iter) => iter.next()?, - TokenTreeIter::Stable(iter) => return iter.next(), + TokenTreeIter::Compiler(iter) => iter.next()?, + TokenTreeIter::Fallback(iter) => return iter.next(), }; Some(match token { - proc_macro::TokenTree::Group(tt) => ::Group::_new(Group::Nightly(tt)).into(), + proc_macro::TokenTree::Group(tt) => ::Group::_new(Group::Compiler(tt)).into(), proc_macro::TokenTree::Punct(tt) => { let spacing = match tt.spacing() { proc_macro::Spacing::Joint => Spacing::Joint, proc_macro::Spacing::Alone => Spacing::Alone, }; let mut o = Punct::new(tt.as_char(), spacing); - o.set_span(::Span::_new(Span::Nightly(tt.span()))); + o.set_span(::Span::_new(Span::Compiler(tt.span()))); o.into() } - proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Nightly(s)).into(), - proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Nightly(l)).into(), + proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Compiler(s)).into(), + proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Compiler(l)).into(), }) } fn size_hint(&self) -> (usize, Option) { match self { - TokenTreeIter::Nightly(tts) => tts.size_hint(), - TokenTreeIter::Stable(tts) => tts.size_hint(), + TokenTreeIter::Compiler(tts) => tts.size_hint(), + TokenTreeIter::Fallback(tts) => tts.size_hint(), } } } @@ -387,28 +377,28 @@ impl fmt::Debug for TokenTreeIter { #[derive(Clone, PartialEq, Eq)] #[cfg(super_unstable)] pub enum SourceFile { - Nightly(proc_macro::SourceFile), - Stable(stable::SourceFile), + Compiler(proc_macro::SourceFile), + Fallback(fallback::SourceFile), } #[cfg(super_unstable)] impl SourceFile { fn nightly(sf: proc_macro::SourceFile) -> Self { - SourceFile::Nightly(sf) + SourceFile::Compiler(sf) } /// Get the path to this source file as a string. pub fn path(&self) -> PathBuf { match self { - SourceFile::Nightly(a) => a.path(), - SourceFile::Stable(a) => a.path(), + SourceFile::Compiler(a) => a.path(), + SourceFile::Fallback(a) => a.path(), } } pub fn is_real(&self) -> bool { match self { - SourceFile::Nightly(a) => a.is_real(), - SourceFile::Stable(a) => a.is_real(), + SourceFile::Compiler(a) => a.is_real(), + SourceFile::Fallback(a) => a.is_real(), } } } @@ -417,12 +407,13 @@ impl SourceFile { impl fmt::Debug for SourceFile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - SourceFile::Nightly(a) => a.fmt(f), - SourceFile::Stable(a) => a.fmt(f), + SourceFile::Compiler(a) => a.fmt(f), + SourceFile::Fallback(a) => a.fmt(f), } } } +#[cfg(any(super_unstable, feature = "span-locations"))] pub struct LineColumn { pub line: usize, pub column: usize, @@ -430,33 +421,33 @@ pub struct LineColumn { #[derive(Copy, Clone)] pub enum Span { - Nightly(proc_macro::Span), - Stable(stable::Span), + Compiler(proc_macro::Span), + Fallback(fallback::Span), } impl Span { pub fn call_site() -> Span { if nightly_works() { - Span::Nightly(proc_macro::Span::call_site()) + Span::Compiler(proc_macro::Span::call_site()) } else { - Span::Stable(stable::Span::call_site()) + Span::Fallback(fallback::Span::call_site()) } } #[cfg(super_unstable)] pub fn def_site() -> Span { if nightly_works() { - Span::Nightly(proc_macro::Span::def_site()) + Span::Compiler(proc_macro::Span::def_site()) } else { - Span::Stable(stable::Span::def_site()) + Span::Fallback(fallback::Span::def_site()) } } #[cfg(super_unstable)] pub fn resolved_at(&self, other: Span) -> Span { match (self, other) { - (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.resolved_at(b)), - (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.resolved_at(b)), + (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), + (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), _ => mismatch(), } } @@ -464,50 +455,56 @@ impl Span { #[cfg(super_unstable)] pub fn located_at(&self, other: Span) -> Span { match (self, other) { - (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.located_at(b)), - (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.located_at(b)), + (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), + (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), _ => mismatch(), } } - pub fn unstable(self) -> proc_macro::Span { + pub fn unwrap(self) -> proc_macro::Span { match self { - Span::Nightly(s) => s, - Span::Stable(_) => mismatch(), + Span::Compiler(s) => s, + Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), } } #[cfg(super_unstable)] pub fn source_file(&self) -> SourceFile { match self { - Span::Nightly(s) => SourceFile::nightly(s.source_file()), - Span::Stable(s) => SourceFile::Stable(s.source_file()), + Span::Compiler(s) => SourceFile::nightly(s.source_file()), + Span::Fallback(s) => SourceFile::Fallback(s.source_file()), } } - #[cfg(super_unstable)] + #[cfg(any(super_unstable, feature = "span-locations"))] pub fn start(&self) -> LineColumn { match self { - Span::Nightly(s) => { + #[cfg(proc_macro_span)] + Span::Compiler(s) => { let proc_macro::LineColumn { line, column } = s.start(); LineColumn { line, column } } - Span::Stable(s) => { - let stable::LineColumn { line, column } = s.start(); + #[cfg(not(proc_macro_span))] + Span::Compiler(_) => LineColumn { line: 0, column: 0 }, + Span::Fallback(s) => { + let fallback::LineColumn { line, column } = s.start(); LineColumn { line, column } } } } - #[cfg(super_unstable)] + #[cfg(any(super_unstable, feature = "span-locations"))] pub fn end(&self) -> LineColumn { match self { - Span::Nightly(s) => { + #[cfg(proc_macro_span)] + Span::Compiler(s) => { let proc_macro::LineColumn { line, column } = s.end(); LineColumn { line, column } } - Span::Stable(s) => { - let stable::LineColumn { line, column } = s.end(); + #[cfg(not(proc_macro_span))] + Span::Compiler(_) => LineColumn { line: 0, column: 0 }, + Span::Fallback(s) => { + let fallback::LineColumn { line, column } = s.end(); LineColumn { line, column } } } @@ -516,8 +513,8 @@ impl Span { #[cfg(super_unstable)] pub fn join(&self, other: Span) -> Option { let ret = match (self, other) { - (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.join(b)?), - (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.join(b)?), + (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?), + (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), _ => return None, }; Some(ret) @@ -526,134 +523,143 @@ impl Span { #[cfg(super_unstable)] pub fn eq(&self, other: &Span) -> bool { match (self, other) { - (Span::Nightly(a), Span::Nightly(b)) => a.eq(b), - (Span::Stable(a), Span::Stable(b)) => a.eq(b), + (Span::Compiler(a), Span::Compiler(b)) => a.eq(b), + (Span::Fallback(a), Span::Fallback(b)) => a.eq(b), _ => false, } } fn unwrap_nightly(self) -> proc_macro::Span { match self { - Span::Nightly(s) => s, - Span::Stable(_) => mismatch(), + Span::Compiler(s) => s, + Span::Fallback(_) => mismatch(), } } } impl From for ::Span { fn from(proc_span: proc_macro::Span) -> ::Span { - ::Span::_new(Span::Nightly(proc_span)) + ::Span::_new(Span::Compiler(proc_span)) } } -impl From for Span { - fn from(inner: stable::Span) -> Span { - Span::Stable(inner) +impl From for Span { + fn from(inner: fallback::Span) -> Span { + Span::Fallback(inner) } } impl fmt::Debug for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Span::Nightly(s) => s.fmt(f), - Span::Stable(s) => s.fmt(f), + Span::Compiler(s) => s.fmt(f), + Span::Fallback(s) => s.fmt(f), } } } +pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { + match span { + Span::Compiler(s) => { + debug.field("span", &s); + } + Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s), + } +} + #[derive(Clone)] pub enum Group { - Nightly(proc_macro::Group), - Stable(stable::Group), + Compiler(proc_macro::Group), + Fallback(fallback::Group), } impl Group { pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { match stream { - TokenStream::Nightly(stream) => { + TokenStream::Compiler(stream) => { let delimiter = match delimiter { Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis, Delimiter::Bracket => proc_macro::Delimiter::Bracket, Delimiter::Brace => proc_macro::Delimiter::Brace, Delimiter::None => proc_macro::Delimiter::None, }; - Group::Nightly(proc_macro::Group::new(delimiter, stream)) + Group::Compiler(proc_macro::Group::new(delimiter, stream)) } - TokenStream::Stable(stream) => { - Group::Stable(stable::Group::new(delimiter, stream)) + TokenStream::Fallback(stream) => { + Group::Fallback(fallback::Group::new(delimiter, stream)) } } } pub fn delimiter(&self) -> Delimiter { match self { - Group::Nightly(g) => match g.delimiter() { + Group::Compiler(g) => match g.delimiter() { proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis, proc_macro::Delimiter::Bracket => Delimiter::Bracket, proc_macro::Delimiter::Brace => Delimiter::Brace, proc_macro::Delimiter::None => Delimiter::None, - } - Group::Stable(g) => g.delimiter(), + }, + Group::Fallback(g) => g.delimiter(), } } pub fn stream(&self) -> TokenStream { match self { - Group::Nightly(g) => TokenStream::Nightly(g.stream()), - Group::Stable(g) => TokenStream::Stable(g.stream()), + Group::Compiler(g) => TokenStream::Compiler(g.stream()), + Group::Fallback(g) => TokenStream::Fallback(g.stream()), } } pub fn span(&self) -> Span { match self { - Group::Nightly(g) => Span::Nightly(g.span()), - Group::Stable(g) => Span::Stable(g.span()), + Group::Compiler(g) => Span::Compiler(g.span()), + Group::Fallback(g) => Span::Fallback(g.span()), } } #[cfg(super_unstable)] pub fn span_open(&self) -> Span { match self { - Group::Nightly(g) => Span::Nightly(g.span_open()), - Group::Stable(g) => Span::Stable(g.span_open()), + Group::Compiler(g) => Span::Compiler(g.span_open()), + Group::Fallback(g) => Span::Fallback(g.span_open()), } } #[cfg(super_unstable)] pub fn span_close(&self) -> Span { match self { - Group::Nightly(g) => Span::Nightly(g.span_close()), - Group::Stable(g) => Span::Stable(g.span_close()), + Group::Compiler(g) => Span::Compiler(g.span_close()), + Group::Fallback(g) => Span::Fallback(g.span_close()), } } pub fn set_span(&mut self, span: Span) { match (self, span) { - (Group::Nightly(g), Span::Nightly(s)) => g.set_span(s), - (Group::Stable(g), Span::Stable(s)) => g.set_span(s), + (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s), + (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s), _ => mismatch(), } } fn unwrap_nightly(self) -> proc_macro::Group { match self { - Group::Nightly(g) => g, - Group::Stable(_) => mismatch(), + Group::Compiler(g) => g, + Group::Fallback(_) => mismatch(), } } } -impl From for Group { - fn from(g: stable::Group) -> Self { - Group::Stable(g) +impl From for Group { + fn from(g: fallback::Group) -> Self { + Group::Fallback(g) } } impl fmt::Display for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { - Group::Nightly(group) => group.fmt(formatter), - Group::Stable(group) => group.fmt(formatter), + Group::Compiler(group) => group.fmt(formatter), + Group::Fallback(group) => group.fmt(formatter), } } } @@ -661,29 +667,29 @@ impl fmt::Display for Group { impl fmt::Debug for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { - Group::Nightly(group) => group.fmt(formatter), - Group::Stable(group) => group.fmt(formatter), + Group::Compiler(group) => group.fmt(formatter), + Group::Fallback(group) => group.fmt(formatter), } } } #[derive(Clone)] pub enum Ident { - Nightly(proc_macro::Ident), - Stable(stable::Ident), + Compiler(proc_macro::Ident), + Fallback(fallback::Ident), } impl Ident { pub fn new(string: &str, span: Span) -> Ident { match span { - Span::Nightly(s) => Ident::Nightly(proc_macro::Ident::new(string, s)), - Span::Stable(s) => Ident::Stable(stable::Ident::new(string, s)), + Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), + Span::Fallback(s) => Ident::Fallback(fallback::Ident::new(string, s)), } } pub fn new_raw(string: &str, span: Span) -> Ident { match span { - Span::Nightly(s) => { + Span::Compiler(s) => { let p: proc_macro::TokenStream = string.parse().unwrap(); let ident = match p.into_iter().next() { Some(proc_macro::TokenTree::Ident(mut i)) => { @@ -692,31 +698,31 @@ impl Ident { } _ => panic!(), }; - Ident::Nightly(ident) + Ident::Compiler(ident) } - Span::Stable(s) => Ident::Stable(stable::Ident::new_raw(string, s)), + Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw(string, s)), } } pub fn span(&self) -> Span { match self { - Ident::Nightly(t) => Span::Nightly(t.span()), - Ident::Stable(t) => Span::Stable(t.span()), + Ident::Compiler(t) => Span::Compiler(t.span()), + Ident::Fallback(t) => Span::Fallback(t.span()), } } pub fn set_span(&mut self, span: Span) { match (self, span) { - (Ident::Nightly(t), Span::Nightly(s)) => t.set_span(s), - (Ident::Stable(t), Span::Stable(s)) => t.set_span(s), + (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s), + (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s), _ => mismatch(), } } fn unwrap_nightly(self) -> proc_macro::Ident { match self { - Ident::Nightly(s) => s, - Ident::Stable(_) => mismatch(), + Ident::Compiler(s) => s, + Ident::Fallback(_) => mismatch(), } } } @@ -724,8 +730,8 @@ impl Ident { impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { match (self, other) { - (Ident::Nightly(t), Ident::Nightly(o)) => t.to_string() == o.to_string(), - (Ident::Stable(t), Ident::Stable(o)) => t == o, + (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(), + (Ident::Fallback(t), Ident::Fallback(o)) => t == o, _ => mismatch(), } } @@ -738,8 +744,8 @@ where fn eq(&self, other: &T) -> bool { let other = other.as_ref(); match self { - Ident::Nightly(t) => t.to_string() == other, - Ident::Stable(t) => t == other, + Ident::Compiler(t) => t.to_string() == other, + Ident::Fallback(t) => t == other, } } } @@ -747,8 +753,8 @@ where impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Ident::Nightly(t) => t.fmt(f), - Ident::Stable(t) => t.fmt(f), + Ident::Compiler(t) => t.fmt(f), + Ident::Fallback(t) => t.fmt(f), } } } @@ -756,25 +762,25 @@ impl fmt::Display for Ident { impl fmt::Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Ident::Nightly(t) => t.fmt(f), - Ident::Stable(t) => t.fmt(f), + Ident::Compiler(t) => t.fmt(f), + Ident::Fallback(t) => t.fmt(f), } } } #[derive(Clone)] pub enum Literal { - Nightly(proc_macro::Literal), - Stable(stable::Literal), + Compiler(proc_macro::Literal), + Fallback(fallback::Literal), } macro_rules! suffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( pub fn $name(n: $kind) -> Literal { if nightly_works() { - Literal::Nightly(proc_macro::Literal::$name(n)) + Literal::Compiler(proc_macro::Literal::$name(n)) } else { - Literal::Stable(stable::Literal::$name(n)) + Literal::Fallback(fallback::Literal::$name(n)) } } )*) @@ -784,9 +790,9 @@ macro_rules! unsuffixed_integers { ($($name:ident => $kind:ident,)*) => ($( pub fn $name(n: $kind) -> Literal { if nightly_works() { - Literal::Nightly(proc_macro::Literal::$name(n)) + Literal::Compiler(proc_macro::Literal::$name(n)) } else { - Literal::Stable(stable::Literal::$name(n)) + Literal::Fallback(fallback::Literal::$name(n)) } } )*) @@ -836,78 +842,78 @@ impl Literal { pub fn f32_unsuffixed(f: f32) -> Literal { if nightly_works() { - Literal::Nightly(proc_macro::Literal::f32_unsuffixed(f)) + Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) } else { - Literal::Stable(stable::Literal::f32_unsuffixed(f)) + Literal::Fallback(fallback::Literal::f32_unsuffixed(f)) } } pub fn f64_unsuffixed(f: f64) -> Literal { if nightly_works() { - Literal::Nightly(proc_macro::Literal::f64_unsuffixed(f)) + Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) } else { - Literal::Stable(stable::Literal::f64_unsuffixed(f)) + Literal::Fallback(fallback::Literal::f64_unsuffixed(f)) } } pub fn string(t: &str) -> Literal { if nightly_works() { - Literal::Nightly(proc_macro::Literal::string(t)) + Literal::Compiler(proc_macro::Literal::string(t)) } else { - Literal::Stable(stable::Literal::string(t)) + Literal::Fallback(fallback::Literal::string(t)) } } pub fn character(t: char) -> Literal { if nightly_works() { - Literal::Nightly(proc_macro::Literal::character(t)) + Literal::Compiler(proc_macro::Literal::character(t)) } else { - Literal::Stable(stable::Literal::character(t)) + Literal::Fallback(fallback::Literal::character(t)) } } pub fn byte_string(bytes: &[u8]) -> Literal { if nightly_works() { - Literal::Nightly(proc_macro::Literal::byte_string(bytes)) + Literal::Compiler(proc_macro::Literal::byte_string(bytes)) } else { - Literal::Stable(stable::Literal::byte_string(bytes)) + Literal::Fallback(fallback::Literal::byte_string(bytes)) } } pub fn span(&self) -> Span { match self { - Literal::Nightly(lit) => Span::Nightly(lit.span()), - Literal::Stable(lit) => Span::Stable(lit.span()), + Literal::Compiler(lit) => Span::Compiler(lit.span()), + Literal::Fallback(lit) => Span::Fallback(lit.span()), } } pub fn set_span(&mut self, span: Span) { match (self, span) { - (Literal::Nightly(lit), Span::Nightly(s)) => lit.set_span(s), - (Literal::Stable(lit), Span::Stable(s)) => lit.set_span(s), + (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s), + (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s), _ => mismatch(), } } fn unwrap_nightly(self) -> proc_macro::Literal { match self { - Literal::Nightly(s) => s, - Literal::Stable(_) => mismatch(), + Literal::Compiler(s) => s, + Literal::Fallback(_) => mismatch(), } } } -impl From for Literal { - fn from(s: stable::Literal) -> Literal { - Literal::Stable(s) +impl From for Literal { + fn from(s: fallback::Literal) -> Literal { + Literal::Fallback(s) } } impl fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Literal::Nightly(t) => t.fmt(f), - Literal::Stable(t) => t.fmt(f), + Literal::Compiler(t) => t.fmt(f), + Literal::Fallback(t) => t.fmt(f), } } } @@ -915,8 +921,8 @@ impl fmt::Display for Literal { impl fmt::Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Literal::Nightly(t) => t.fmt(f), - Literal::Stable(t) => t.fmt(f), + Literal::Compiler(t) => t.fmt(f), + Literal::Fallback(t) => t.fmt(f), } } } diff --git a/vendor/proc-macro2/tests/test.rs b/vendor/proc-macro2/tests/test.rs index 9d37cf37d2..370392b65c 100644 --- a/vendor/proc-macro2/tests/test.rs +++ b/vendor/proc-macro2/tests/test.rs @@ -5,7 +5,7 @@ use std::str::{self, FromStr}; use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree}; #[test] -fn terms() { +fn idents() { assert_eq!( Ident::new("String", Span::call_site()).to_string(), "String" @@ -16,7 +16,7 @@ fn terms() { #[test] #[cfg(procmacro2_semver_exempt)] -fn raw_terms() { +fn raw_idents() { assert_eq!( Ident::new_raw("String", Span::call_site()).to_string(), "r#String" @@ -27,37 +27,37 @@ fn raw_terms() { #[test] #[should_panic(expected = "Ident is not allowed to be empty; use Option")] -fn term_empty() { +fn ident_empty() { Ident::new("", Span::call_site()); } #[test] #[should_panic(expected = "Ident cannot be a number; use Literal instead")] -fn term_number() { +fn ident_number() { Ident::new("255", Span::call_site()); } #[test] #[should_panic(expected = "\"a#\" is not a valid Ident")] -fn term_invalid() { +fn ident_invalid() { Ident::new("a#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] -fn raw_term_empty() { +fn raw_ident_empty() { Ident::new("r#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] -fn raw_term_number() { +fn raw_ident_number() { Ident::new("r#255", Span::call_site()); } #[test] #[should_panic(expected = "\"r#a#\" is not a valid Ident")] -fn raw_term_invalid() { +fn raw_ident_invalid() { Ident::new("r#a#", Span::call_site()); } @@ -80,9 +80,21 @@ fn lifetime_invalid() { } #[test] -fn literals() { +fn literal_string() { assert_eq!(Literal::string("foo").to_string(), "\"foo\""); assert_eq!(Literal::string("\"").to_string(), "\"\\\"\""); + assert_eq!(Literal::string("didn't").to_string(), "\"didn't\""); +} + +#[test] +fn literal_character() { + assert_eq!(Literal::character('x').to_string(), "'x'"); + assert_eq!(Literal::character('\'').to_string(), "'\\''"); + assert_eq!(Literal::character('"').to_string(), "'\"'"); +} + +#[test] +fn literal_float() { assert_eq!(Literal::f32_unsuffixed(10.0).to_string(), "10.0"); } @@ -137,7 +149,7 @@ fn fail() { fail("r#_"); } -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] #[test] fn span_test() { use proc_macro2::TokenTree; @@ -193,7 +205,7 @@ testing 123 } #[cfg(procmacro2_semver_exempt)] -#[cfg(not(feature = "nightly"))] +#[cfg(not(nightly))] #[test] fn default_span() { let start = Span::call_site().start(); @@ -329,12 +341,32 @@ fn test_debug_ident() { } #[test] -#[cfg(not(feature = "nightly"))] fn test_debug_tokenstream() { let tts = TokenStream::from_str("[a + 1]").unwrap(); #[cfg(not(procmacro2_semver_exempt))] let expected = "\ +TokenStream [ + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + sym: a, + }, + Punct { + op: '+', + spacing: Alone, + }, + Literal { + lit: 1, + }, + ], + }, +]\ + "; + + #[cfg(not(procmacro2_semver_exempt))] + let expected_before_trailing_commas = "\ TokenStream [ Group { delimiter: Bracket, @@ -356,6 +388,31 @@ TokenStream [ #[cfg(procmacro2_semver_exempt)] let expected = "\ +TokenStream [ + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + sym: a, + span: bytes(2..3), + }, + Punct { + op: '+', + spacing: Alone, + span: bytes(4..5), + }, + Literal { + lit: 1, + span: bytes(6..7), + }, + ], + span: bytes(1..8), + }, +]\ + "; + + #[cfg(procmacro2_semver_exempt)] + let expected_before_trailing_commas = "\ TokenStream [ Group { delimiter: Bracket, @@ -379,7 +436,12 @@ TokenStream [ ]\ "; - assert_eq!(expected, format!("{:#?}", tts)); + let actual = format!("{:#?}", tts); + if actual.ends_with(",\n]") { + assert_eq!(expected, actual); + } else { + assert_eq!(expected_before_trailing_commas, actual); + } } #[test] diff --git a/vendor/pulldown-cmark-0.1.2/.cargo-checksum.json b/vendor/pulldown-cmark-0.1.2/.cargo-checksum.json deleted file mode 100644 index 2eb1d573ef..0000000000 --- a/vendor/pulldown-cmark-0.1.2/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CONTRIBUTING.md":"8f3a78ee312b1d3010d7061cf08a92a54235452e9834d2b541b292ad8fe56611","Cargo.toml":"624301ad312e09b72c3c5da0c77db982d8f937845a55b89b9e6a7ae6b5472af4","LICENSE":"c4f10f55904bdb9f27d3fbf94c354926d6cfe8b982276e556238c258941b243b","README.md":"6be857b798e3199e6d4de025597c3bca5f1fb0dae405138d1f70734b285fd387","build.rs":"add15d061e63f9d3e843bbd3389247c1d08a90f3bf309d5866fccc9ceef8c598","specs/footnotes.txt":"8593e211895904e861c85f786552f3dc2fe3d9eaa73c36ec1d2731416a8dbe4a","specs/table.txt":"c90cc0275515c495d2bff529562803f9b628adbc7805b2145c7a7415d8bb655b","src/entities.rs":"146f254dc83a12a4df0343b40e3a8690fb1b5b5175a110123aced7fbaf360871","src/escape.rs":"47c69dcc2cd76882c29b167bbcb63e784a041feac5898735a437c85ade578cda","src/html.rs":"5c7821ac541c23aecc46a0ea0135f50f84a7bf4e362549f6c8d3c51f48790e2b","src/lib.rs":"8298de06c2e7204d38f28290dbd83ba127543f28598235bddcc344b951ba9a58","src/main.rs":"ddee35ce1f06e4311e0383d527818643afc6a4efd765e0c2bcab36113e9aa7a3","src/parse.rs":"38cc115bd7210370a4c6ff999862754f2a8c16026f7d1e2a01025ed53aee5a10","src/passes.rs":"891224f1bbc69e9016acd537e33996e76480f321d02b1e58cb76c5e4b9045e9e","src/puncttable.rs":"6787a03f708e23851ef6e7ca636d15978c33ba3e8fcb6778a09762a8baa47870","src/scanners.rs":"180c169ab05d584726e59acb129f092b2491d972d2dec6624ad4169bb0e906a7","src/utils.rs":"6400643f6b85d96b2e91166ab4701a007dba6ac40fa2b349a466d1a1b97bb843","tests/errors.rs":"430ba3ec553da7e77594c13286cec0f99d3e34631f6f9f79d5659a4ca446f4b5","tests/footnotes.rs":"b8fe6c536fb9559741e01a55be14a1df866c7106ee7fbcaf89ca6bf2eb45da3f","tests/html.rs":"e4a566eceec5c926602c9ccc12d428a60c0f260ea899e78fbf3fb69c82d1ad02","tests/spec.rs":"3e7b534837971f5e40ca0d2af6a2f667d93f39711cf832116dac7ddd6951116a","tests/table.rs":"b43e7824c0ce96ec0f72c6394a67b5a46bb12fa78e6f3d9f6502362ce504baed","third_party/CommonMark/LICENSE":"3026a329eb5a8c5814f48bb1047970ace2a7d877c4973401a24b5563d76e345a","third_party/CommonMark/README.google":"a89d8075d323bda7871772288f3c43be1efb0d1bee2bb25b592278e45bc5c926","third_party/CommonMark/spec.txt":"20d5deca1a4f8cfc0f46034a32a3b4bdeaf609cdafdcd6457d1ca41650e0a1c7","tools/mk_entities.py":"a88f6a00413822644a00b146d39918d5a97e5092afdd30ce4ed0465b2ed4f315","tools/mk_puncttable.py":"5001dbf67e0009f2e23dbdfd50986564cdae977c611379c4b9d888366caa1d5e"},"package":"d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"} \ No newline at end of file diff --git a/vendor/pulldown-cmark-0.1.2/CONTRIBUTING.md b/vendor/pulldown-cmark-0.1.2/CONTRIBUTING.md deleted file mode 100644 index 1ba853922f..0000000000 --- a/vendor/pulldown-cmark-0.1.2/CONTRIBUTING.md +++ /dev/null @@ -1,24 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. We -use Github pull requests for this purpose. - -### The small print -Contributions made by corporations are covered by a different agreement than -the one above, the Software Grant and Corporate Contributor License Agreement. diff --git a/vendor/pulldown-cmark-0.1.2/README.md b/vendor/pulldown-cmark-0.1.2/README.md deleted file mode 100644 index 7fa7ae4e57..0000000000 --- a/vendor/pulldown-cmark-0.1.2/README.md +++ /dev/null @@ -1,124 +0,0 @@ -# pulldown-cmark - -[Documentation](https://docs.rs/pulldown-cmark/) - -This library is a pull parser for [CommonMark](http://commonmark.org/), written -in [Rust](http://www.rust-lang.org/). It comes with a simple command-line tool, -useful for rendering to HTML, and is also designed to be easy to use from as -a library. - -It is designed to be: - -* Fast; a bare minimum of allocation and copying -* Safe; written in pure Rust with no unsafe blocks -* Versatile; in particular source-maps are supported -* Correct; the goal is 100% compliance with the [CommonMark spec](http://spec.commonmark.org/) - -## Why a pull parser? - -There are many parsers for Markdown and its variants, but to my knowledge none -use pull parsing. Pull parsing has become popular for XML, especially for -memory-conscious applications, because it uses dramatically less memory than -construcing a document tree, but is much easier to use than push parsers. Push -parsers are notoriously difficult to use, and also often error-prone because of -the need for user to delicately juggle state in a series of callbacks. - -In a clean design, the parsing and rendering stages are neatly separated, but -this is often sacrificed in the name of performance and expedience. Many Markdown -implementations mix parsing and rendering together, and even designs that try -to separate them (such as the popular [hoedown](https://github.com/hoedown/hoedown)), -make the assumption that the rendering process can be fully represented as a -serialized string. - -Pull parsing is in some sense the most versatile architecture. It's possible to -drive a push interface, also with minimal memory, and quite straightforward to -construct an AST. Another advantage is that source-map information (the mapping -between parsed blocks and offsets within the source text) is readily available; -you basically just call `get_offset()` as you consume events. - -While manipulating AST's is the most flexible way to transform documents, -operating on iterators is surprisingly easy, and quite efficient. Here, for -example, is the code to transform soft line breaks into hard breaks: - -```rust -let parser = parser.map(|event| match event { - Event::SoftBreak => Event::HardBreak, - _ => event -}); -``` - -Or expanding an abbreviation in text: - -```rust -let parser = parser.map(|event| match event { - Event::Str(text) => Event::Str(text.replace("abbr", "abbreviation")), - _ => event -}); -``` - -Another simple example is code to determine the max nesting level: - -```rust -let mut max_nesting = 0; -let mut level = 0; -for event in parser { - match event { - Event::Start(_) => { - level += 1; - max_nesting = std::cmp::max(max_nesting, level); - } - Event::End(_) => level -= 1, - _ => () - } -} -``` - -## Using Rust idiomatically - -A lot of the internal scanning code is written at a pretty low level (it -pretty much scans byte patterns for the bits of syntax), but the external -interface is designed to be idiomatic Rust. - -Pull parsers are at heart an iterator of events (start and end tags, text, -and other bits and pieces). The parser data structure implements the -Rust Iterator trait directly, and Event is an enum. Thus, you can use the -full power and expressivity of Rust's iterator infrastructure, including -for loops and `map` (as in the examples above), collecting the events into -a vector (for recording, playback, and manipulation), and more. - -Further, the Str event (representing text) is a copy-on-write string (note: -this isn't quite true yet). The vast majority of text fragments are just -slices of the source document. For these, copy-on-write gives a convenient -representation that requires no allocation or copying, but allocated -strings are available when they're needed. Thus, when rendering text to -HTML, most text is copied just once, from the source document to the -HTML buffer. - -## Building only the pulldown-cmark library - -By default, the binary is built as well. If you don't want/need it, then build like this: - -```bash -> cargo build --no-default-features -``` - -Or put in your `Cargo.toml` file: - -```toml -pulldown-cmark = { version = "0.0.11", default-features = false } -``` - -## Authors - -The main author is Raph Levien. - -## Contributions - -We gladly accept contributions via GitHub pull requests, as long as the author -has signed the Google Contributor License. Please see CONTRIBUTIONS.md for -more details. - -### Disclaimer - -This is not an official Google product (experimental or otherwise), it -is just code that happens to be owned by Google. diff --git a/vendor/pulldown-cmark-0.1.2/build.rs b/vendor/pulldown-cmark-0.1.2/build.rs deleted file mode 100644 index 5681027803..0000000000 --- a/vendor/pulldown-cmark-0.1.2/build.rs +++ /dev/null @@ -1,152 +0,0 @@ - -fn main() { - generate_tests_from_spec() -} - -// If the "gen-tests" feature is absent, -// this function will be compiled down to nothing -#[cfg(not(feature="gen-tests"))] -fn generate_tests_from_spec() {} - -// If the feature is present, generate tests -// from any .txt file present in the specs/ directory -// -// Test cases are present in the files in the -// following format: -// -// ```````````````````````````````` example -// markdown -// . -// expected html output -// ```````````````````````````````` -#[cfg(feature="gen-tests")] -fn generate_tests_from_spec() { - use std::path::{PathBuf}; - use std::fs::{self, File}; - use std::io::{Read, Write}; - - // This is a hardcoded path to the CommonMark spec because it is not situated in - // the specs/ directory. It's in an array to easily chain it to the other iterator - // and make it easy to eventually add other hardcoded paths in the future if needed - let hardcoded = ["./third_party/CommonMark/spec.txt"]; - let hardcoded_iter = hardcoded.into_iter() - .map(PathBuf::from); - - // Create an iterator over the files in the specs/ directory that have a .txt extension - let spec_files = fs::read_dir("./specs") - .expect("Could not find the 'specs' directory") - .filter_map(Result::ok) - .map(|d| d.path()) - .filter(|p| p.extension().map(|e| e.to_owned()).is_some()) - .chain(hardcoded_iter); - - for file_path in spec_files { - let mut raw_spec = String::new(); - - File::open(&file_path) - .and_then(|mut f| f.read_to_string(&mut raw_spec)) - .expect("Could not read the spec file"); - - let rs_test_file = PathBuf::from("./tests/") - .join(file_path.file_name().expect("Invalid filename")) - .with_extension("rs"); - - let mut spec_rs = File::create(&rs_test_file) - .expect(&format!("Could not create {:?}", rs_test_file)); - - let spec_name = file_path.file_stem().unwrap().to_str().unwrap(); - - let spec = Spec::new(&raw_spec); - let mut n_tests = 0; - - spec_rs.write(b"// This file is auto-generated by the build script\n").unwrap(); - spec_rs.write(b"// Please, do not modify it manually\n").unwrap(); - spec_rs.write(b"\nextern crate pulldown_cmark;\n").unwrap(); - - for (i, testcase) in spec.enumerate() { - spec_rs.write_fmt( - format_args!( - r###" - - #[test] - fn {}_test_{i}() {{ - let original = r##"{original}"##; - let expected = r##"{expected}"##; - - use pulldown_cmark::{{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}}; - - let mut s = String::new(); - - let mut opts = Options::empty(); - opts.insert(OPTION_ENABLE_TABLES); - opts.insert(OPTION_ENABLE_FOOTNOTES); - - let p = Parser::new_ext(&original, opts); - html::push_html(&mut s, p); - - assert_eq!(expected, s); - }}"###, - spec_name, - i=i+1, - original=testcase.original, - expected=testcase.expected - ), - ).unwrap(); - - n_tests += 1; - } - - println!("cargo:warning=Generated {} tests in {:?}", n_tests, rs_test_file); - } -} - -#[cfg(feature="gen-tests")] -pub struct Spec<'a> { - spec: &'a str, -} - -#[cfg(feature="gen-tests")] -impl<'a> Spec<'a> { - pub fn new(spec: &'a str) -> Self { - Spec{ spec: spec } - } -} - -#[cfg(feature="gen-tests")] -pub struct TestCase { - pub original: String, - pub expected: String, -} - -#[cfg(feature="gen-tests")] -impl<'a> Iterator for Spec<'a> { - type Item = TestCase; - - fn next(&mut self) -> Option { - let spec = self.spec; - - let i_start = match self.spec.find("```````````````````````````````` example\n").map(|pos| pos + 41) { - Some(pos) => pos, - None => return None, - }; - - let i_end = match self.spec[i_start..].find("\n.\n").map(|pos| (pos + 1) + i_start){ - Some(pos) => pos, - None => return None, - }; - - let e_end = match self.spec[i_end + 2..].find("````````````````````````````````\n").map(|pos| pos + i_end + 2){ - Some(pos) => pos, - None => return None, - }; - - self.spec = &self.spec[e_end + 33 ..]; - - let test_case = TestCase { - original: spec[i_start .. i_end].to_string().replace("→", "\t"), - expected: spec[i_end + 2 .. e_end].to_string().replace("→", "\t") - }; - - Some(test_case) - } -} diff --git a/vendor/pulldown-cmark-0.1.2/specs/footnotes.txt b/vendor/pulldown-cmark-0.1.2/specs/footnotes.txt deleted file mode 100644 index 4b91b38456..0000000000 --- a/vendor/pulldown-cmark-0.1.2/specs/footnotes.txt +++ /dev/null @@ -1,153 +0,0 @@ -Run this with `cargo run -- -F -s specs/footnotes.txt`. - -This is how footnotes are basically used. - -```````````````````````````````` example -Lorem ipsum.[^a] - -[^a]: Cool. -. -

    Lorem ipsum.1

    -
    1 -

    Cool.

    -
    -```````````````````````````````` - - -Footnotes can be used inside blockquotes: - -```````````````````````````````` example -> This is the song that never ends.\ -> Yes it goes on and on my friends.[^lambchops] -> -> [^lambchops]: -. -
    -

    This is the song that never ends.
    -Yes it goes on and on my friends.1

    - -
    -```````````````````````````````` - - -Footnotes can be complex block structures: - -```````````````````````````````` example -Songs that simply loop are a popular way to annoy people. [^examples] - -[^examples]: - * [The song that never ends](https://www.youtube.com/watch?v=0U2zJOryHKQ) - * [I know a song that gets on everybody's nerves](https://www.youtube.com/watch?v=TehWI09qxls) - * [Ninety-nine bottles of beer on the wall](https://www.youtube.com/watch?v=qVjCag8XoHQ) -. -

    Songs that simply loop are a popular way to annoy people. 1

    - -```````````````````````````````` - - -Footnotes can even have multiple paragraphs. They also don't need to be referenced to show up. - -```````````````````````````````` example -[^lorem]: If heaven ever wishes to grant me a boon, it will be a total effacing of the results of a mere chance which fixed my eye on a certain stray piece of shelf-paper. It was nothing on which I would naturally have stumbled in the course of my daily round, for it was an old number of an Australian journal, the Sydney Bulletin for April 18, 1925. It had escaped even the cutting bureau which had at the time of its issuance been avidly collecting material for my uncle's research. - -I had largely given over my inquiries into what Professor Angell called the "Cthulhu Cult", and was visiting a learned friend in Paterson, New Jersey; the curator of a local museum and a mineralogist of note. Examining one day the reserve specimens roughly set on the storage shelves in a rear room of the museum, my eye was caught by an odd picture in one of the old papers spread beneath the stones. It was the Sydney Bulletin I have mentioned, for my friend had wide affiliations in all conceivable foreign parts; and the picture was a half-tone cut of a hideous stone image almost identical with that which Legrasse had found in the swamp. -. -
    1 -

    If heaven ever wishes to grant me a boon, it will be a total effacing of the results of a mere chance which fixed my eye on a certain stray piece of shelf-paper. It was nothing on which I would naturally have stumbled in the course of my daily round, for it was an old number of an Australian journal, the Sydney Bulletin for April 18, 1925. It had escaped even the cutting bureau which had at the time of its issuance been avidly collecting material for my uncle's research.

    -
    -

    I had largely given over my inquiries into what Professor Angell called the "Cthulhu Cult", and was visiting a learned friend in Paterson, New Jersey; the curator of a local museum and a mineralogist of note. Examining one day the reserve specimens roughly set on the storage shelves in a rear room of the museum, my eye was caught by an odd picture in one of the old papers spread beneath the stones. It was the Sydney Bulletin I have mentioned, for my friend had wide affiliations in all conceivable foreign parts; and the picture was a half-tone cut of a hideous stone image almost identical with that which Legrasse had found in the swamp.

    -```````````````````````````````` - - -A footnote will end on a single line break. Note that this behavior changed in version -0.1.0, to become more like hoedown. See issue #21. - -```````````````````````````````` example -[^ipsum]: How much wood would a woodchuck chuck. - -If a woodchuck could chuck wood. - - -# Forms of entertainment that aren't childish -. -
    1 -

    How much wood would a woodchuck chuck.

    -
    -

    If a woodchuck could chuck wood.

    -

    Forms of entertainment that aren't childish

    -```````````````````````````````` - - -A footnote will also break if it's inside another container. - -```````````````````````````````` example -> He's also really stupid. [^why] -> -> [^why]: Because your mamma! - -As such, we can guarantee that the non-childish forms of entertainment are probably more entertaining to adults, since, having had a whole childhood doing the childish ones, the non-childish ones are merely the ones that haven't gotten boring yet. -. -
    -

    He's also really stupid. 1

    -
    1 -

    Because your mamma!

    -
    -
    -

    As such, we can guarantee that the non-childish forms of entertainment are probably more entertaining to adults, since, having had a whole childhood doing the childish ones, the non-childish ones are merely the ones that haven't gotten boring yet.

    -```````````````````````````````` - - -As a special exception, footnotes cannot be nested directly inside each other. - -```````````````````````````````` example -Nested footnotes are considered poor style. [^a] [^xkcd] - -[^a]: This does not mean that footnotes cannot reference each other. [^b] - -[^b]: This means that a footnote definition cannot be directly inside another footnote definition. -> This means that a footnote cannot be directly inside another footnote's body. [^e] -> -> [^e]: They can, however, be inside anything else. - -[^xkcd]: [The other kind of nested footnote is, however, considered poor style.](https://xkcd.com/1208/) -. -

    Nested footnotes are considered poor style. 1 2

    -
    1 -

    This does not mean that footnotes cannot reference each other. 3

    -
    -
    3 -

    This means that a footnote definition cannot be directly inside another footnote definition.

    -
    -

    This means that a footnote cannot be directly inside another footnote's body. 4

    -
    4 -

    They can, however, be inside anything else.

    -
    -
    -
    - -```````````````````````````````` - -They do need one line between each other. - -```````````````````````````````` example -[^Doh] Ray Me Fa So La Te Do! [^1] - -[^Doh]: I know. Wrong Doe. And it won't render right. -[^1]: Common for people practicing music. -. -

    1 Ray Me Fa So La Te Do! 2

    -
    1 -

    I know. Wrong Doe. And it won't render right. -2: Common for people practicing music.

    -
    -```````````````````````````````` diff --git a/vendor/pulldown-cmark-0.1.2/specs/table.txt b/vendor/pulldown-cmark-0.1.2/specs/table.txt deleted file mode 100644 index 2187b8d5de..0000000000 --- a/vendor/pulldown-cmark-0.1.2/specs/table.txt +++ /dev/null @@ -1,214 +0,0 @@ -Run this with `cargo run -- -T -s specs/table.txt`. - -False match -=========== - -```````````````````````````````` example -Test header ------------ -. -

    Test header

    -```````````````````````````````` - - -True match -========== - -```````````````````````````````` example -Test|Table -----|----- -. - -
    TestTable
    -```````````````````````````````` - - -Actual rows in it -================= - -```````````````````````````````` example -Test|Table -----|----- -Test row -Test|2 - -Test ending -. - - - -
    TestTable
    Test row
    Test2
    -

    Test ending

    -```````````````````````````````` - - -Test with quote -=============== - -```````````````````````````````` example -> Test | Table -> ------|------ -> Row 1 | Every -> Row 2 | Day -> -> Paragraph -. -
    - - - -
    Test Table
    Row 1 Every
    Row 2 Day
    -

    Paragraph

    -
    -```````````````````````````````` - - -Test with list -============== - -```````````````````````````````` example - 1. First entry - 2. Second entry - - Col 1|Col 2 - -|- - Row 1|Part 2 - Row 2|Part 2 -. -
      -
    1. -

      First entry

      -
    2. -
    3. -

      Second entry

      - - - -
      Col 1Col 2
      Row 1Part 2
      Row 2Part 2
      -
    4. -
    -```````````````````````````````` - - -Test with border -================ - -```````````````````````````````` example -|Col 1|Col 2| -|-----|-----| -|R1C1 |R1C2 | -|R2C1 |R2C2 | -. - - - -
    Col 1Col 2
    R1C1 R1C2
    R2C1 R2C2
    -```````````````````````````````` - - -Test with empty cells -===================== - -Empty cells should work. - -```````````````````````````````` example -| Col 1 | Col 2 | -|-------|-------| -| | | -| | | -. - - - -
    Col 1 Col 2
    -```````````````````````````````` - -... and properly mix with filled cells. - -```````````````````````````````` example -| Col 1 | Col 2 | -|-------|-------| -| x | | -| | x | -. - - - -
    Col 1 Col 2
    x
    x
    -```````````````````````````````` - - -Table with UTF-8 -================ - -Basic example. - -```````````````````````````````` example -|Col 1|Col 2| -|-----|-----| -|✓ |✓ | -|✓ |✓ | -. - - - -
    Col 1Col 2
    ✓ ✓
    ✓ ✓
    -```````````````````````````````` - -More advanced example. - -```````````````````````````````` example -| Target | std |rustc|cargo| notes | -|-------------------------------|-----|-----|-----|----------------------------| -| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL | -| `arm-linux-androideabi` | ✓ | | | ARM Android | -| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) | -| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) | -| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) | -| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) | -. - - - - - - - - -
    Target std rustccargo notes
    x86_64-unknown-linux-musl ✓ 64-bit Linux with MUSL
    arm-linux-androideabi ✓ ARM Android
    arm-unknown-linux-gnueabi ✓ ✓ ARM Linux (2.6.18+)
    arm-unknown-linux-gnueabihf ✓ ✓ ARM Linux (2.6.18+)
    aarch64-unknown-linux-gnu ✓ ARM64 Linux (2.6.18+)
    mips-unknown-linux-gnu ✓ MIPS Linux (2.6.18+)
    mipsel-unknown-linux-gnu ✓ MIPS (LE) Linux (2.6.18+)
    -```````````````````````````````` - -Hiragana-containing pseudo-table. - -```````````````````````````````` example -|-|-| -|ぃ|い| -. -

    |-|-| -|ぃ|い|

    -```````````````````````````````` - -Hiragana-containing actual table. - -```````````````````````````````` example -|ぁ|ぃ| -|-|-| -|ぃ|ぃ| -. - - -
    ぁぃ
    ぃぃ
    -```````````````````````````````` - -Test russian symbols. - -```````````````````````````````` example -|Колонка 1|Колонка 2| -|---------|---------| -|Ячейка 1 |Ячейка 2 | -. - - -
    Колонка 1Колонка 2
    Ячейка 1 Ячейка 2
    -```````````````````````````````` diff --git a/vendor/pulldown-cmark-0.1.2/src/entities.rs b/vendor/pulldown-cmark-0.1.2/src/entities.rs deleted file mode 100644 index 8c5049461b..0000000000 --- a/vendor/pulldown-cmark-0.1.2/src/entities.rs +++ /dev/null @@ -1,4284 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Expansions of HTML5 entities - -// Autogenerated by mk_entities.py - -const ENTITIES: [&'static str; 2125] = [ - "AElig", - "AMP", - "Aacute", - "Abreve", - "Acirc", - "Acy", - "Afr", - "Agrave", - "Alpha", - "Amacr", - "And", - "Aogon", - "Aopf", - "ApplyFunction", - "Aring", - "Ascr", - "Assign", - "Atilde", - "Auml", - "Backslash", - "Barv", - "Barwed", - "Bcy", - "Because", - "Bernoullis", - "Beta", - "Bfr", - "Bopf", - "Breve", - "Bscr", - "Bumpeq", - "CHcy", - "COPY", - "Cacute", - "Cap", - "CapitalDifferentialD", - "Cayleys", - "Ccaron", - "Ccedil", - "Ccirc", - "Cconint", - "Cdot", - "Cedilla", - "CenterDot", - "Cfr", - "Chi", - "CircleDot", - "CircleMinus", - "CirclePlus", - "CircleTimes", - "ClockwiseContourIntegral", - "CloseCurlyDoubleQuote", - "CloseCurlyQuote", - "Colon", - "Colone", - "Congruent", - "Conint", - "ContourIntegral", - "Copf", - "Coproduct", - "CounterClockwiseContourIntegral", - "Cross", - "Cscr", - "Cup", - "CupCap", - "DD", - "DDotrahd", - "DJcy", - "DScy", - "DZcy", - "Dagger", - "Darr", - "Dashv", - "Dcaron", - "Dcy", - "Del", - "Delta", - "Dfr", - "DiacriticalAcute", - "DiacriticalDot", - "DiacriticalDoubleAcute", - "DiacriticalGrave", - "DiacriticalTilde", - "Diamond", - "DifferentialD", - "Dopf", - "Dot", - "DotDot", - "DotEqual", - "DoubleContourIntegral", - "DoubleDot", - "DoubleDownArrow", - "DoubleLeftArrow", - "DoubleLeftRightArrow", - "DoubleLeftTee", - "DoubleLongLeftArrow", - "DoubleLongLeftRightArrow", - "DoubleLongRightArrow", - "DoubleRightArrow", - "DoubleRightTee", - "DoubleUpArrow", - "DoubleUpDownArrow", - "DoubleVerticalBar", - "DownArrow", - "DownArrowBar", - "DownArrowUpArrow", - "DownBreve", - "DownLeftRightVector", - "DownLeftTeeVector", - "DownLeftVector", - "DownLeftVectorBar", - "DownRightTeeVector", - "DownRightVector", - "DownRightVectorBar", - "DownTee", - "DownTeeArrow", - "Downarrow", - "Dscr", - "Dstrok", - "ENG", - "ETH", - "Eacute", - "Ecaron", - "Ecirc", - "Ecy", - "Edot", - "Efr", - "Egrave", - "Element", - "Emacr", - "EmptySmallSquare", - "EmptyVerySmallSquare", - "Eogon", - "Eopf", - "Epsilon", - "Equal", - "EqualTilde", - "Equilibrium", - "Escr", - "Esim", - "Eta", - "Euml", - "Exists", - "ExponentialE", - "Fcy", - "Ffr", - "FilledSmallSquare", - "FilledVerySmallSquare", - "Fopf", - "ForAll", - "Fouriertrf", - "Fscr", - "GJcy", - "GT", - "Gamma", - "Gammad", - "Gbreve", - "Gcedil", - "Gcirc", - "Gcy", - "Gdot", - "Gfr", - "Gg", - "Gopf", - "GreaterEqual", - "GreaterEqualLess", - "GreaterFullEqual", - "GreaterGreater", - "GreaterLess", - "GreaterSlantEqual", - "GreaterTilde", - "Gscr", - "Gt", - "HARDcy", - "Hacek", - "Hat", - "Hcirc", - "Hfr", - "HilbertSpace", - "Hopf", - "HorizontalLine", - "Hscr", - "Hstrok", - "HumpDownHump", - "HumpEqual", - "IEcy", - "IJlig", - "IOcy", - "Iacute", - "Icirc", - "Icy", - "Idot", - "Ifr", - "Igrave", - "Im", - "Imacr", - "ImaginaryI", - "Implies", - "Int", - "Integral", - "Intersection", - "InvisibleComma", - "InvisibleTimes", - "Iogon", - "Iopf", - "Iota", - "Iscr", - "Itilde", - "Iukcy", - "Iuml", - "Jcirc", - "Jcy", - "Jfr", - "Jopf", - "Jscr", - "Jsercy", - "Jukcy", - "KHcy", - "KJcy", - "Kappa", - "Kcedil", - "Kcy", - "Kfr", - "Kopf", - "Kscr", - "LJcy", - "LT", - "Lacute", - "Lambda", - "Lang", - "Laplacetrf", - "Larr", - "Lcaron", - "Lcedil", - "Lcy", - "LeftAngleBracket", - "LeftArrow", - "LeftArrowBar", - "LeftArrowRightArrow", - "LeftCeiling", - "LeftDoubleBracket", - "LeftDownTeeVector", - "LeftDownVector", - "LeftDownVectorBar", - "LeftFloor", - "LeftRightArrow", - "LeftRightVector", - "LeftTee", - "LeftTeeArrow", - "LeftTeeVector", - "LeftTriangle", - "LeftTriangleBar", - "LeftTriangleEqual", - "LeftUpDownVector", - "LeftUpTeeVector", - "LeftUpVector", - "LeftUpVectorBar", - "LeftVector", - "LeftVectorBar", - "Leftarrow", - "Leftrightarrow", - "LessEqualGreater", - "LessFullEqual", - "LessGreater", - "LessLess", - "LessSlantEqual", - "LessTilde", - "Lfr", - "Ll", - "Lleftarrow", - "Lmidot", - "LongLeftArrow", - "LongLeftRightArrow", - "LongRightArrow", - "Longleftarrow", - "Longleftrightarrow", - "Longrightarrow", - "Lopf", - "LowerLeftArrow", - "LowerRightArrow", - "Lscr", - "Lsh", - "Lstrok", - "Lt", - "Map", - "Mcy", - "MediumSpace", - "Mellintrf", - "Mfr", - "MinusPlus", - "Mopf", - "Mscr", - "Mu", - "NJcy", - "Nacute", - "Ncaron", - "Ncedil", - "Ncy", - "NegativeMediumSpace", - "NegativeThickSpace", - "NegativeThinSpace", - "NegativeVeryThinSpace", - "NestedGreaterGreater", - "NestedLessLess", - "NewLine", - "Nfr", - "NoBreak", - "NonBreakingSpace", - "Nopf", - "Not", - "NotCongruent", - "NotCupCap", - "NotDoubleVerticalBar", - "NotElement", - "NotEqual", - "NotEqualTilde", - "NotExists", - "NotGreater", - "NotGreaterEqual", - "NotGreaterFullEqual", - "NotGreaterGreater", - "NotGreaterLess", - "NotGreaterSlantEqual", - "NotGreaterTilde", - "NotHumpDownHump", - "NotHumpEqual", - "NotLeftTriangle", - "NotLeftTriangleBar", - "NotLeftTriangleEqual", - "NotLess", - "NotLessEqual", - "NotLessGreater", - "NotLessLess", - "NotLessSlantEqual", - "NotLessTilde", - "NotNestedGreaterGreater", - "NotNestedLessLess", - "NotPrecedes", - "NotPrecedesEqual", - "NotPrecedesSlantEqual", - "NotReverseElement", - "NotRightTriangle", - "NotRightTriangleBar", - "NotRightTriangleEqual", - "NotSquareSubset", - "NotSquareSubsetEqual", - "NotSquareSuperset", - "NotSquareSupersetEqual", - "NotSubset", - "NotSubsetEqual", - "NotSucceeds", - "NotSucceedsEqual", - "NotSucceedsSlantEqual", - "NotSucceedsTilde", - "NotSuperset", - "NotSupersetEqual", - "NotTilde", - "NotTildeEqual", - "NotTildeFullEqual", - "NotTildeTilde", - "NotVerticalBar", - "Nscr", - "Ntilde", - "Nu", - "OElig", - "Oacute", - "Ocirc", - "Ocy", - "Odblac", - "Ofr", - "Ograve", - "Omacr", - "Omega", - "Omicron", - "Oopf", - "OpenCurlyDoubleQuote", - "OpenCurlyQuote", - "Or", - "Oscr", - "Oslash", - "Otilde", - "Otimes", - "Ouml", - "OverBar", - "OverBrace", - "OverBracket", - "OverParenthesis", - "PartialD", - "Pcy", - "Pfr", - "Phi", - "Pi", - "PlusMinus", - "Poincareplane", - "Popf", - "Pr", - "Precedes", - "PrecedesEqual", - "PrecedesSlantEqual", - "PrecedesTilde", - "Prime", - "Product", - "Proportion", - "Proportional", - "Pscr", - "Psi", - "QUOT", - "Qfr", - "Qopf", - "Qscr", - "RBarr", - "REG", - "Racute", - "Rang", - "Rarr", - "Rarrtl", - "Rcaron", - "Rcedil", - "Rcy", - "Re", - "ReverseElement", - "ReverseEquilibrium", - "ReverseUpEquilibrium", - "Rfr", - "Rho", - "RightAngleBracket", - "RightArrow", - "RightArrowBar", - "RightArrowLeftArrow", - "RightCeiling", - "RightDoubleBracket", - "RightDownTeeVector", - "RightDownVector", - "RightDownVectorBar", - "RightFloor", - "RightTee", - "RightTeeArrow", - "RightTeeVector", - "RightTriangle", - "RightTriangleBar", - "RightTriangleEqual", - "RightUpDownVector", - "RightUpTeeVector", - "RightUpVector", - "RightUpVectorBar", - "RightVector", - "RightVectorBar", - "Rightarrow", - "Ropf", - "RoundImplies", - "Rrightarrow", - "Rscr", - "Rsh", - "RuleDelayed", - "SHCHcy", - "SHcy", - "SOFTcy", - "Sacute", - "Sc", - "Scaron", - "Scedil", - "Scirc", - "Scy", - "Sfr", - "ShortDownArrow", - "ShortLeftArrow", - "ShortRightArrow", - "ShortUpArrow", - "Sigma", - "SmallCircle", - "Sopf", - "Sqrt", - "Square", - "SquareIntersection", - "SquareSubset", - "SquareSubsetEqual", - "SquareSuperset", - "SquareSupersetEqual", - "SquareUnion", - "Sscr", - "Star", - "Sub", - "Subset", - "SubsetEqual", - "Succeeds", - "SucceedsEqual", - "SucceedsSlantEqual", - "SucceedsTilde", - "SuchThat", - "Sum", - "Sup", - "Superset", - "SupersetEqual", - "Supset", - "THORN", - "TRADE", - "TSHcy", - "TScy", - "Tab", - "Tau", - "Tcaron", - "Tcedil", - "Tcy", - "Tfr", - "Therefore", - "Theta", - "ThickSpace", - "ThinSpace", - "Tilde", - "TildeEqual", - "TildeFullEqual", - "TildeTilde", - "Topf", - "TripleDot", - "Tscr", - "Tstrok", - "Uacute", - "Uarr", - "Uarrocir", - "Ubrcy", - "Ubreve", - "Ucirc", - "Ucy", - "Udblac", - "Ufr", - "Ugrave", - "Umacr", - "UnderBar", - "UnderBrace", - "UnderBracket", - "UnderParenthesis", - "Union", - "UnionPlus", - "Uogon", - "Uopf", - "UpArrow", - "UpArrowBar", - "UpArrowDownArrow", - "UpDownArrow", - "UpEquilibrium", - "UpTee", - "UpTeeArrow", - "Uparrow", - "Updownarrow", - "UpperLeftArrow", - "UpperRightArrow", - "Upsi", - "Upsilon", - "Uring", - "Uscr", - "Utilde", - "Uuml", - "VDash", - "Vbar", - "Vcy", - "Vdash", - "Vdashl", - "Vee", - "Verbar", - "Vert", - "VerticalBar", - "VerticalLine", - "VerticalSeparator", - "VerticalTilde", - "VeryThinSpace", - "Vfr", - "Vopf", - "Vscr", - "Vvdash", - "Wcirc", - "Wedge", - "Wfr", - "Wopf", - "Wscr", - "Xfr", - "Xi", - "Xopf", - "Xscr", - "YAcy", - "YIcy", - "YUcy", - "Yacute", - "Ycirc", - "Ycy", - "Yfr", - "Yopf", - "Yscr", - "Yuml", - "ZHcy", - "Zacute", - "Zcaron", - "Zcy", - "Zdot", - "ZeroWidthSpace", - "Zeta", - "Zfr", - "Zopf", - "Zscr", - "aacute", - "abreve", - "ac", - "acE", - "acd", - "acirc", - "acute", - "acy", - "aelig", - "af", - "afr", - "agrave", - "alefsym", - "aleph", - "alpha", - "amacr", - "amalg", - "amp", - "and", - "andand", - "andd", - "andslope", - "andv", - "ang", - "ange", - "angle", - "angmsd", - "angmsdaa", - "angmsdab", - "angmsdac", - "angmsdad", - "angmsdae", - "angmsdaf", - "angmsdag", - "angmsdah", - "angrt", - "angrtvb", - "angrtvbd", - "angsph", - "angst", - "angzarr", - "aogon", - "aopf", - "ap", - "apE", - "apacir", - "ape", - "apid", - "apos", - "approx", - "approxeq", - "aring", - "ascr", - "ast", - "asymp", - "asympeq", - "atilde", - "auml", - "awconint", - "awint", - "bNot", - "backcong", - "backepsilon", - "backprime", - "backsim", - "backsimeq", - "barvee", - "barwed", - "barwedge", - "bbrk", - "bbrktbrk", - "bcong", - "bcy", - "bdquo", - "becaus", - "because", - "bemptyv", - "bepsi", - "bernou", - "beta", - "beth", - "between", - "bfr", - "bigcap", - "bigcirc", - "bigcup", - "bigodot", - "bigoplus", - "bigotimes", - "bigsqcup", - "bigstar", - "bigtriangledown", - "bigtriangleup", - "biguplus", - "bigvee", - "bigwedge", - "bkarow", - "blacklozenge", - "blacksquare", - "blacktriangle", - "blacktriangledown", - "blacktriangleleft", - "blacktriangleright", - "blank", - "blk12", - "blk14", - "blk34", - "block", - "bne", - "bnequiv", - "bnot", - "bopf", - "bot", - "bottom", - "bowtie", - "boxDL", - "boxDR", - "boxDl", - "boxDr", - "boxH", - "boxHD", - "boxHU", - "boxHd", - "boxHu", - "boxUL", - "boxUR", - "boxUl", - "boxUr", - "boxV", - "boxVH", - "boxVL", - "boxVR", - "boxVh", - "boxVl", - "boxVr", - "boxbox", - "boxdL", - "boxdR", - "boxdl", - "boxdr", - "boxh", - "boxhD", - "boxhU", - "boxhd", - "boxhu", - "boxminus", - "boxplus", - "boxtimes", - "boxuL", - "boxuR", - "boxul", - "boxur", - "boxv", - "boxvH", - "boxvL", - "boxvR", - "boxvh", - "boxvl", - "boxvr", - "bprime", - "breve", - "brvbar", - "bscr", - "bsemi", - "bsim", - "bsime", - "bsol", - "bsolb", - "bsolhsub", - "bull", - "bullet", - "bump", - "bumpE", - "bumpe", - "bumpeq", - "cacute", - "cap", - "capand", - "capbrcup", - "capcap", - "capcup", - "capdot", - "caps", - "caret", - "caron", - "ccaps", - "ccaron", - "ccedil", - "ccirc", - "ccups", - "ccupssm", - "cdot", - "cedil", - "cemptyv", - "cent", - "centerdot", - "cfr", - "chcy", - "check", - "checkmark", - "chi", - "cir", - "cirE", - "circ", - "circeq", - "circlearrowleft", - "circlearrowright", - "circledR", - "circledS", - "circledast", - "circledcirc", - "circleddash", - "cire", - "cirfnint", - "cirmid", - "cirscir", - "clubs", - "clubsuit", - "colon", - "colone", - "coloneq", - "comma", - "commat", - "comp", - "compfn", - "complement", - "complexes", - "cong", - "congdot", - "conint", - "copf", - "coprod", - "copy", - "copysr", - "crarr", - "cross", - "cscr", - "csub", - "csube", - "csup", - "csupe", - "ctdot", - "cudarrl", - "cudarrr", - "cuepr", - "cuesc", - "cularr", - "cularrp", - "cup", - "cupbrcap", - "cupcap", - "cupcup", - "cupdot", - "cupor", - "cups", - "curarr", - "curarrm", - "curlyeqprec", - "curlyeqsucc", - "curlyvee", - "curlywedge", - "curren", - "curvearrowleft", - "curvearrowright", - "cuvee", - "cuwed", - "cwconint", - "cwint", - "cylcty", - "dArr", - "dHar", - "dagger", - "daleth", - "darr", - "dash", - "dashv", - "dbkarow", - "dblac", - "dcaron", - "dcy", - "dd", - "ddagger", - "ddarr", - "ddotseq", - "deg", - "delta", - "demptyv", - "dfisht", - "dfr", - "dharl", - "dharr", - "diam", - "diamond", - "diamondsuit", - "diams", - "die", - "digamma", - "disin", - "div", - "divide", - "divideontimes", - "divonx", - "djcy", - "dlcorn", - "dlcrop", - "dollar", - "dopf", - "dot", - "doteq", - "doteqdot", - "dotminus", - "dotplus", - "dotsquare", - "doublebarwedge", - "downarrow", - "downdownarrows", - "downharpoonleft", - "downharpoonright", - "drbkarow", - "drcorn", - "drcrop", - "dscr", - "dscy", - "dsol", - "dstrok", - "dtdot", - "dtri", - "dtrif", - "duarr", - "duhar", - "dwangle", - "dzcy", - "dzigrarr", - "eDDot", - "eDot", - "eacute", - "easter", - "ecaron", - "ecir", - "ecirc", - "ecolon", - "ecy", - "edot", - "ee", - "efDot", - "efr", - "eg", - "egrave", - "egs", - "egsdot", - "el", - "elinters", - "ell", - "els", - "elsdot", - "emacr", - "empty", - "emptyset", - "emptyv", - "emsp", - "emsp13", - "emsp14", - "eng", - "ensp", - "eogon", - "eopf", - "epar", - "eparsl", - "eplus", - "epsi", - "epsilon", - "epsiv", - "eqcirc", - "eqcolon", - "eqsim", - "eqslantgtr", - "eqslantless", - "equals", - "equest", - "equiv", - "equivDD", - "eqvparsl", - "erDot", - "erarr", - "escr", - "esdot", - "esim", - "eta", - "eth", - "euml", - "euro", - "excl", - "exist", - "expectation", - "exponentiale", - "fallingdotseq", - "fcy", - "female", - "ffilig", - "fflig", - "ffllig", - "ffr", - "filig", - "fjlig", - "flat", - "fllig", - "fltns", - "fnof", - "fopf", - "forall", - "fork", - "forkv", - "fpartint", - "frac12", - "frac13", - "frac14", - "frac15", - "frac16", - "frac18", - "frac23", - "frac25", - "frac34", - "frac35", - "frac38", - "frac45", - "frac56", - "frac58", - "frac78", - "frasl", - "frown", - "fscr", - "gE", - "gEl", - "gacute", - "gamma", - "gammad", - "gap", - "gbreve", - "gcirc", - "gcy", - "gdot", - "ge", - "gel", - "geq", - "geqq", - "geqslant", - "ges", - "gescc", - "gesdot", - "gesdoto", - "gesdotol", - "gesl", - "gesles", - "gfr", - "gg", - "ggg", - "gimel", - "gjcy", - "gl", - "glE", - "gla", - "glj", - "gnE", - "gnap", - "gnapprox", - "gne", - "gneq", - "gneqq", - "gnsim", - "gopf", - "grave", - "gscr", - "gsim", - "gsime", - "gsiml", - "gt", - "gtcc", - "gtcir", - "gtdot", - "gtlPar", - "gtquest", - "gtrapprox", - "gtrarr", - "gtrdot", - "gtreqless", - "gtreqqless", - "gtrless", - "gtrsim", - "gvertneqq", - "gvnE", - "hArr", - "hairsp", - "half", - "hamilt", - "hardcy", - "harr", - "harrcir", - "harrw", - "hbar", - "hcirc", - "hearts", - "heartsuit", - "hellip", - "hercon", - "hfr", - "hksearow", - "hkswarow", - "hoarr", - "homtht", - "hookleftarrow", - "hookrightarrow", - "hopf", - "horbar", - "hscr", - "hslash", - "hstrok", - "hybull", - "hyphen", - "iacute", - "ic", - "icirc", - "icy", - "iecy", - "iexcl", - "iff", - "ifr", - "igrave", - "ii", - "iiiint", - "iiint", - "iinfin", - "iiota", - "ijlig", - "imacr", - "image", - "imagline", - "imagpart", - "imath", - "imof", - "imped", - "in", - "incare", - "infin", - "infintie", - "inodot", - "int", - "intcal", - "integers", - "intercal", - "intlarhk", - "intprod", - "iocy", - "iogon", - "iopf", - "iota", - "iprod", - "iquest", - "iscr", - "isin", - "isinE", - "isindot", - "isins", - "isinsv", - "isinv", - "it", - "itilde", - "iukcy", - "iuml", - "jcirc", - "jcy", - "jfr", - "jmath", - "jopf", - "jscr", - "jsercy", - "jukcy", - "kappa", - "kappav", - "kcedil", - "kcy", - "kfr", - "kgreen", - "khcy", - "kjcy", - "kopf", - "kscr", - "lAarr", - "lArr", - "lAtail", - "lBarr", - "lE", - "lEg", - "lHar", - "lacute", - "laemptyv", - "lagran", - "lambda", - "lang", - "langd", - "langle", - "lap", - "laquo", - "larr", - "larrb", - "larrbfs", - "larrfs", - "larrhk", - "larrlp", - "larrpl", - "larrsim", - "larrtl", - "lat", - "latail", - "late", - "lates", - "lbarr", - "lbbrk", - "lbrace", - "lbrack", - "lbrke", - "lbrksld", - "lbrkslu", - "lcaron", - "lcedil", - "lceil", - "lcub", - "lcy", - "ldca", - "ldquo", - "ldquor", - "ldrdhar", - "ldrushar", - "ldsh", - "le", - "leftarrow", - "leftarrowtail", - "leftharpoondown", - "leftharpoonup", - "leftleftarrows", - "leftrightarrow", - "leftrightarrows", - "leftrightharpoons", - "leftrightsquigarrow", - "leftthreetimes", - "leg", - "leq", - "leqq", - "leqslant", - "les", - "lescc", - "lesdot", - "lesdoto", - "lesdotor", - "lesg", - "lesges", - "lessapprox", - "lessdot", - "lesseqgtr", - "lesseqqgtr", - "lessgtr", - "lesssim", - "lfisht", - "lfloor", - "lfr", - "lg", - "lgE", - "lhard", - "lharu", - "lharul", - "lhblk", - "ljcy", - "ll", - "llarr", - "llcorner", - "llhard", - "lltri", - "lmidot", - "lmoust", - "lmoustache", - "lnE", - "lnap", - "lnapprox", - "lne", - "lneq", - "lneqq", - "lnsim", - "loang", - "loarr", - "lobrk", - "longleftarrow", - "longleftrightarrow", - "longmapsto", - "longrightarrow", - "looparrowleft", - "looparrowright", - "lopar", - "lopf", - "loplus", - "lotimes", - "lowast", - "lowbar", - "loz", - "lozenge", - "lozf", - "lpar", - "lparlt", - "lrarr", - "lrcorner", - "lrhar", - "lrhard", - "lrm", - "lrtri", - "lsaquo", - "lscr", - "lsh", - "lsim", - "lsime", - "lsimg", - "lsqb", - "lsquo", - "lsquor", - "lstrok", - "lt", - "ltcc", - "ltcir", - "ltdot", - "lthree", - "ltimes", - "ltlarr", - "ltquest", - "ltrPar", - "ltri", - "ltrie", - "ltrif", - "lurdshar", - "luruhar", - "lvertneqq", - "lvnE", - "mDDot", - "macr", - "male", - "malt", - "maltese", - "map", - "mapsto", - "mapstodown", - "mapstoleft", - "mapstoup", - "marker", - "mcomma", - "mcy", - "mdash", - "measuredangle", - "mfr", - "mho", - "micro", - "mid", - "midast", - "midcir", - "middot", - "minus", - "minusb", - "minusd", - "minusdu", - "mlcp", - "mldr", - "mnplus", - "models", - "mopf", - "mp", - "mscr", - "mstpos", - "mu", - "multimap", - "mumap", - "nGg", - "nGt", - "nGtv", - "nLeftarrow", - "nLeftrightarrow", - "nLl", - "nLt", - "nLtv", - "nRightarrow", - "nVDash", - "nVdash", - "nabla", - "nacute", - "nang", - "nap", - "napE", - "napid", - "napos", - "napprox", - "natur", - "natural", - "naturals", - "nbsp", - "nbump", - "nbumpe", - "ncap", - "ncaron", - "ncedil", - "ncong", - "ncongdot", - "ncup", - "ncy", - "ndash", - "ne", - "neArr", - "nearhk", - "nearr", - "nearrow", - "nedot", - "nequiv", - "nesear", - "nesim", - "nexist", - "nexists", - "nfr", - "ngE", - "nge", - "ngeq", - "ngeqq", - "ngeqslant", - "nges", - "ngsim", - "ngt", - "ngtr", - "nhArr", - "nharr", - "nhpar", - "ni", - "nis", - "nisd", - "niv", - "njcy", - "nlArr", - "nlE", - "nlarr", - "nldr", - "nle", - "nleftarrow", - "nleftrightarrow", - "nleq", - "nleqq", - "nleqslant", - "nles", - "nless", - "nlsim", - "nlt", - "nltri", - "nltrie", - "nmid", - "nopf", - "not", - "notin", - "notinE", - "notindot", - "notinva", - "notinvb", - "notinvc", - "notni", - "notniva", - "notnivb", - "notnivc", - "npar", - "nparallel", - "nparsl", - "npart", - "npolint", - "npr", - "nprcue", - "npre", - "nprec", - "npreceq", - "nrArr", - "nrarr", - "nrarrc", - "nrarrw", - "nrightarrow", - "nrtri", - "nrtrie", - "nsc", - "nsccue", - "nsce", - "nscr", - "nshortmid", - "nshortparallel", - "nsim", - "nsime", - "nsimeq", - "nsmid", - "nspar", - "nsqsube", - "nsqsupe", - "nsub", - "nsubE", - "nsube", - "nsubset", - "nsubseteq", - "nsubseteqq", - "nsucc", - "nsucceq", - "nsup", - "nsupE", - "nsupe", - "nsupset", - "nsupseteq", - "nsupseteqq", - "ntgl", - "ntilde", - "ntlg", - "ntriangleleft", - "ntrianglelefteq", - "ntriangleright", - "ntrianglerighteq", - "nu", - "num", - "numero", - "numsp", - "nvDash", - "nvHarr", - "nvap", - "nvdash", - "nvge", - "nvgt", - "nvinfin", - "nvlArr", - "nvle", - "nvlt", - "nvltrie", - "nvrArr", - "nvrtrie", - "nvsim", - "nwArr", - "nwarhk", - "nwarr", - "nwarrow", - "nwnear", - "oS", - "oacute", - "oast", - "ocir", - "ocirc", - "ocy", - "odash", - "odblac", - "odiv", - "odot", - "odsold", - "oelig", - "ofcir", - "ofr", - "ogon", - "ograve", - "ogt", - "ohbar", - "ohm", - "oint", - "olarr", - "olcir", - "olcross", - "oline", - "olt", - "omacr", - "omega", - "omicron", - "omid", - "ominus", - "oopf", - "opar", - "operp", - "oplus", - "or", - "orarr", - "ord", - "order", - "orderof", - "ordf", - "ordm", - "origof", - "oror", - "orslope", - "orv", - "oscr", - "oslash", - "osol", - "otilde", - "otimes", - "otimesas", - "ouml", - "ovbar", - "par", - "para", - "parallel", - "parsim", - "parsl", - "part", - "pcy", - "percnt", - "period", - "permil", - "perp", - "pertenk", - "pfr", - "phi", - "phiv", - "phmmat", - "phone", - "pi", - "pitchfork", - "piv", - "planck", - "planckh", - "plankv", - "plus", - "plusacir", - "plusb", - "pluscir", - "plusdo", - "plusdu", - "pluse", - "plusmn", - "plussim", - "plustwo", - "pm", - "pointint", - "popf", - "pound", - "pr", - "prE", - "prap", - "prcue", - "pre", - "prec", - "precapprox", - "preccurlyeq", - "preceq", - "precnapprox", - "precneqq", - "precnsim", - "precsim", - "prime", - "primes", - "prnE", - "prnap", - "prnsim", - "prod", - "profalar", - "profline", - "profsurf", - "prop", - "propto", - "prsim", - "prurel", - "pscr", - "psi", - "puncsp", - "qfr", - "qint", - "qopf", - "qprime", - "qscr", - "quaternions", - "quatint", - "quest", - "questeq", - "quot", - "rAarr", - "rArr", - "rAtail", - "rBarr", - "rHar", - "race", - "racute", - "radic", - "raemptyv", - "rang", - "rangd", - "range", - "rangle", - "raquo", - "rarr", - "rarrap", - "rarrb", - "rarrbfs", - "rarrc", - "rarrfs", - "rarrhk", - "rarrlp", - "rarrpl", - "rarrsim", - "rarrtl", - "rarrw", - "ratail", - "ratio", - "rationals", - "rbarr", - "rbbrk", - "rbrace", - "rbrack", - "rbrke", - "rbrksld", - "rbrkslu", - "rcaron", - "rcedil", - "rceil", - "rcub", - "rcy", - "rdca", - "rdldhar", - "rdquo", - "rdquor", - "rdsh", - "real", - "realine", - "realpart", - "reals", - "rect", - "reg", - "rfisht", - "rfloor", - "rfr", - "rhard", - "rharu", - "rharul", - "rho", - "rhov", - "rightarrow", - "rightarrowtail", - "rightharpoondown", - "rightharpoonup", - "rightleftarrows", - "rightleftharpoons", - "rightrightarrows", - "rightsquigarrow", - "rightthreetimes", - "ring", - "risingdotseq", - "rlarr", - "rlhar", - "rlm", - "rmoust", - "rmoustache", - "rnmid", - "roang", - "roarr", - "robrk", - "ropar", - "ropf", - "roplus", - "rotimes", - "rpar", - "rpargt", - "rppolint", - "rrarr", - "rsaquo", - "rscr", - "rsh", - "rsqb", - "rsquo", - "rsquor", - "rthree", - "rtimes", - "rtri", - "rtrie", - "rtrif", - "rtriltri", - "ruluhar", - "rx", - "sacute", - "sbquo", - "sc", - "scE", - "scap", - "scaron", - "sccue", - "sce", - "scedil", - "scirc", - "scnE", - "scnap", - "scnsim", - "scpolint", - "scsim", - "scy", - "sdot", - "sdotb", - "sdote", - "seArr", - "searhk", - "searr", - "searrow", - "sect", - "semi", - "seswar", - "setminus", - "setmn", - "sext", - "sfr", - "sfrown", - "sharp", - "shchcy", - "shcy", - "shortmid", - "shortparallel", - "shy", - "sigma", - "sigmaf", - "sigmav", - "sim", - "simdot", - "sime", - "simeq", - "simg", - "simgE", - "siml", - "simlE", - "simne", - "simplus", - "simrarr", - "slarr", - "smallsetminus", - "smashp", - "smeparsl", - "smid", - "smile", - "smt", - "smte", - "smtes", - "softcy", - "sol", - "solb", - "solbar", - "sopf", - "spades", - "spadesuit", - "spar", - "sqcap", - "sqcaps", - "sqcup", - "sqcups", - "sqsub", - "sqsube", - "sqsubset", - "sqsubseteq", - "sqsup", - "sqsupe", - "sqsupset", - "sqsupseteq", - "squ", - "square", - "squarf", - "squf", - "srarr", - "sscr", - "ssetmn", - "ssmile", - "sstarf", - "star", - "starf", - "straightepsilon", - "straightphi", - "strns", - "sub", - "subE", - "subdot", - "sube", - "subedot", - "submult", - "subnE", - "subne", - "subplus", - "subrarr", - "subset", - "subseteq", - "subseteqq", - "subsetneq", - "subsetneqq", - "subsim", - "subsub", - "subsup", - "succ", - "succapprox", - "succcurlyeq", - "succeq", - "succnapprox", - "succneqq", - "succnsim", - "succsim", - "sum", - "sung", - "sup", - "sup1", - "sup2", - "sup3", - "supE", - "supdot", - "supdsub", - "supe", - "supedot", - "suphsol", - "suphsub", - "suplarr", - "supmult", - "supnE", - "supne", - "supplus", - "supset", - "supseteq", - "supseteqq", - "supsetneq", - "supsetneqq", - "supsim", - "supsub", - "supsup", - "swArr", - "swarhk", - "swarr", - "swarrow", - "swnwar", - "szlig", - "target", - "tau", - "tbrk", - "tcaron", - "tcedil", - "tcy", - "tdot", - "telrec", - "tfr", - "there4", - "therefore", - "theta", - "thetasym", - "thetav", - "thickapprox", - "thicksim", - "thinsp", - "thkap", - "thksim", - "thorn", - "tilde", - "times", - "timesb", - "timesbar", - "timesd", - "tint", - "toea", - "top", - "topbot", - "topcir", - "topf", - "topfork", - "tosa", - "tprime", - "trade", - "triangle", - "triangledown", - "triangleleft", - "trianglelefteq", - "triangleq", - "triangleright", - "trianglerighteq", - "tridot", - "trie", - "triminus", - "triplus", - "trisb", - "tritime", - "trpezium", - "tscr", - "tscy", - "tshcy", - "tstrok", - "twixt", - "twoheadleftarrow", - "twoheadrightarrow", - "uArr", - "uHar", - "uacute", - "uarr", - "ubrcy", - "ubreve", - "ucirc", - "ucy", - "udarr", - "udblac", - "udhar", - "ufisht", - "ufr", - "ugrave", - "uharl", - "uharr", - "uhblk", - "ulcorn", - "ulcorner", - "ulcrop", - "ultri", - "umacr", - "uml", - "uogon", - "uopf", - "uparrow", - "updownarrow", - "upharpoonleft", - "upharpoonright", - "uplus", - "upsi", - "upsih", - "upsilon", - "upuparrows", - "urcorn", - "urcorner", - "urcrop", - "uring", - "urtri", - "uscr", - "utdot", - "utilde", - "utri", - "utrif", - "uuarr", - "uuml", - "uwangle", - "vArr", - "vBar", - "vBarv", - "vDash", - "vangrt", - "varepsilon", - "varkappa", - "varnothing", - "varphi", - "varpi", - "varpropto", - "varr", - "varrho", - "varsigma", - "varsubsetneq", - "varsubsetneqq", - "varsupsetneq", - "varsupsetneqq", - "vartheta", - "vartriangleleft", - "vartriangleright", - "vcy", - "vdash", - "vee", - "veebar", - "veeeq", - "vellip", - "verbar", - "vert", - "vfr", - "vltri", - "vnsub", - "vnsup", - "vopf", - "vprop", - "vrtri", - "vscr", - "vsubnE", - "vsubne", - "vsupnE", - "vsupne", - "vzigzag", - "wcirc", - "wedbar", - "wedge", - "wedgeq", - "weierp", - "wfr", - "wopf", - "wp", - "wr", - "wreath", - "wscr", - "xcap", - "xcirc", - "xcup", - "xdtri", - "xfr", - "xhArr", - "xharr", - "xi", - "xlArr", - "xlarr", - "xmap", - "xnis", - "xodot", - "xopf", - "xoplus", - "xotime", - "xrArr", - "xrarr", - "xscr", - "xsqcup", - "xuplus", - "xutri", - "xvee", - "xwedge", - "yacute", - "yacy", - "ycirc", - "ycy", - "yen", - "yfr", - "yicy", - "yopf", - "yscr", - "yucy", - "yuml", - "zacute", - "zcaron", - "zcy", - "zdot", - "zeetrf", - "zeta", - "zfr", - "zhcy", - "zigrarr", - "zopf", - "zscr", - "zwj", - "zwnj", - ]; - -const ENTITY_VALUES: [&'static str; 2125] = [ - "\u{00C6}", - "\u{0026}", - "\u{00C1}", - "\u{0102}", - "\u{00C2}", - "\u{0410}", - "\u{1D504}", - "\u{00C0}", - "\u{0391}", - "\u{0100}", - "\u{2A53}", - "\u{0104}", - "\u{1D538}", - "\u{2061}", - "\u{00C5}", - "\u{1D49C}", - "\u{2254}", - "\u{00C3}", - "\u{00C4}", - "\u{2216}", - "\u{2AE7}", - "\u{2306}", - "\u{0411}", - "\u{2235}", - "\u{212C}", - "\u{0392}", - "\u{1D505}", - "\u{1D539}", - "\u{02D8}", - "\u{212C}", - "\u{224E}", - "\u{0427}", - "\u{00A9}", - "\u{0106}", - "\u{22D2}", - "\u{2145}", - "\u{212D}", - "\u{010C}", - "\u{00C7}", - "\u{0108}", - "\u{2230}", - "\u{010A}", - "\u{00B8}", - "\u{00B7}", - "\u{212D}", - "\u{03A7}", - "\u{2299}", - "\u{2296}", - "\u{2295}", - "\u{2297}", - "\u{2232}", - "\u{201D}", - "\u{2019}", - "\u{2237}", - "\u{2A74}", - "\u{2261}", - "\u{222F}", - "\u{222E}", - "\u{2102}", - "\u{2210}", - "\u{2233}", - "\u{2A2F}", - "\u{1D49E}", - "\u{22D3}", - "\u{224D}", - "\u{2145}", - "\u{2911}", - "\u{0402}", - "\u{0405}", - "\u{040F}", - "\u{2021}", - "\u{21A1}", - "\u{2AE4}", - "\u{010E}", - "\u{0414}", - "\u{2207}", - "\u{0394}", - "\u{1D507}", - "\u{00B4}", - "\u{02D9}", - "\u{02DD}", - "\u{0060}", - "\u{02DC}", - "\u{22C4}", - "\u{2146}", - "\u{1D53B}", - "\u{00A8}", - "\u{20DC}", - "\u{2250}", - "\u{222F}", - "\u{00A8}", - "\u{21D3}", - "\u{21D0}", - "\u{21D4}", - "\u{2AE4}", - "\u{27F8}", - "\u{27FA}", - "\u{27F9}", - "\u{21D2}", - "\u{22A8}", - "\u{21D1}", - "\u{21D5}", - "\u{2225}", - "\u{2193}", - "\u{2913}", - "\u{21F5}", - "\u{0311}", - "\u{2950}", - "\u{295E}", - "\u{21BD}", - "\u{2956}", - "\u{295F}", - "\u{21C1}", - "\u{2957}", - "\u{22A4}", - "\u{21A7}", - "\u{21D3}", - "\u{1D49F}", - "\u{0110}", - "\u{014A}", - "\u{00D0}", - "\u{00C9}", - "\u{011A}", - "\u{00CA}", - "\u{042D}", - "\u{0116}", - "\u{1D508}", - "\u{00C8}", - "\u{2208}", - "\u{0112}", - "\u{25FB}", - "\u{25AB}", - "\u{0118}", - "\u{1D53C}", - "\u{0395}", - "\u{2A75}", - "\u{2242}", - "\u{21CC}", - "\u{2130}", - "\u{2A73}", - "\u{0397}", - "\u{00CB}", - "\u{2203}", - "\u{2147}", - "\u{0424}", - "\u{1D509}", - "\u{25FC}", - "\u{25AA}", - "\u{1D53D}", - "\u{2200}", - "\u{2131}", - "\u{2131}", - "\u{0403}", - "\u{003E}", - "\u{0393}", - "\u{03DC}", - "\u{011E}", - "\u{0122}", - "\u{011C}", - "\u{0413}", - "\u{0120}", - "\u{1D50A}", - "\u{22D9}", - "\u{1D53E}", - "\u{2265}", - "\u{22DB}", - "\u{2267}", - "\u{2AA2}", - "\u{2277}", - "\u{2A7E}", - "\u{2273}", - "\u{1D4A2}", - "\u{226B}", - "\u{042A}", - "\u{02C7}", - "\u{005E}", - "\u{0124}", - "\u{210C}", - "\u{210B}", - "\u{210D}", - "\u{2500}", - "\u{210B}", - "\u{0126}", - "\u{224E}", - "\u{224F}", - "\u{0415}", - "\u{0132}", - "\u{0401}", - "\u{00CD}", - "\u{00CE}", - "\u{0418}", - "\u{0130}", - "\u{2111}", - "\u{00CC}", - "\u{2111}", - "\u{012A}", - "\u{2148}", - "\u{21D2}", - "\u{222C}", - "\u{222B}", - "\u{22C2}", - "\u{2063}", - "\u{2062}", - "\u{012E}", - "\u{1D540}", - "\u{0399}", - "\u{2110}", - "\u{0128}", - "\u{0406}", - "\u{00CF}", - "\u{0134}", - "\u{0419}", - "\u{1D50D}", - "\u{1D541}", - "\u{1D4A5}", - "\u{0408}", - "\u{0404}", - "\u{0425}", - "\u{040C}", - "\u{039A}", - "\u{0136}", - "\u{041A}", - "\u{1D50E}", - "\u{1D542}", - "\u{1D4A6}", - "\u{0409}", - "\u{003C}", - "\u{0139}", - "\u{039B}", - "\u{27EA}", - "\u{2112}", - "\u{219E}", - "\u{013D}", - "\u{013B}", - "\u{041B}", - "\u{27E8}", - "\u{2190}", - "\u{21E4}", - "\u{21C6}", - "\u{2308}", - "\u{27E6}", - "\u{2961}", - "\u{21C3}", - "\u{2959}", - "\u{230A}", - "\u{2194}", - "\u{294E}", - "\u{22A3}", - "\u{21A4}", - "\u{295A}", - "\u{22B2}", - "\u{29CF}", - "\u{22B4}", - "\u{2951}", - "\u{2960}", - "\u{21BF}", - "\u{2958}", - "\u{21BC}", - "\u{2952}", - "\u{21D0}", - "\u{21D4}", - "\u{22DA}", - "\u{2266}", - "\u{2276}", - "\u{2AA1}", - "\u{2A7D}", - "\u{2272}", - "\u{1D50F}", - "\u{22D8}", - "\u{21DA}", - "\u{013F}", - "\u{27F5}", - "\u{27F7}", - "\u{27F6}", - "\u{27F8}", - "\u{27FA}", - "\u{27F9}", - "\u{1D543}", - "\u{2199}", - "\u{2198}", - "\u{2112}", - "\u{21B0}", - "\u{0141}", - "\u{226A}", - "\u{2905}", - "\u{041C}", - "\u{205F}", - "\u{2133}", - "\u{1D510}", - "\u{2213}", - "\u{1D544}", - "\u{2133}", - "\u{039C}", - "\u{040A}", - "\u{0143}", - "\u{0147}", - "\u{0145}", - "\u{041D}", - "\u{200B}", - "\u{200B}", - "\u{200B}", - "\u{200B}", - "\u{226B}", - "\u{226A}", - "\u{000A}", - "\u{1D511}", - "\u{2060}", - "\u{00A0}", - "\u{2115}", - "\u{2AEC}", - "\u{2262}", - "\u{226D}", - "\u{2226}", - "\u{2209}", - "\u{2260}", - "\u{2242}\u{0338}", - "\u{2204}", - "\u{226F}", - "\u{2271}", - "\u{2267}\u{0338}", - "\u{226B}\u{0338}", - "\u{2279}", - "\u{2A7E}\u{0338}", - "\u{2275}", - "\u{224E}\u{0338}", - "\u{224F}\u{0338}", - "\u{22EA}", - "\u{29CF}\u{0338}", - "\u{22EC}", - "\u{226E}", - "\u{2270}", - "\u{2278}", - "\u{226A}\u{0338}", - "\u{2A7D}\u{0338}", - "\u{2274}", - "\u{2AA2}\u{0338}", - "\u{2AA1}\u{0338}", - "\u{2280}", - "\u{2AAF}\u{0338}", - "\u{22E0}", - "\u{220C}", - "\u{22EB}", - "\u{29D0}\u{0338}", - "\u{22ED}", - "\u{228F}\u{0338}", - "\u{22E2}", - "\u{2290}\u{0338}", - "\u{22E3}", - "\u{2282}\u{20D2}", - "\u{2288}", - "\u{2281}", - "\u{2AB0}\u{0338}", - "\u{22E1}", - "\u{227F}\u{0338}", - "\u{2283}\u{20D2}", - "\u{2289}", - "\u{2241}", - "\u{2244}", - "\u{2247}", - "\u{2249}", - "\u{2224}", - "\u{1D4A9}", - "\u{00D1}", - "\u{039D}", - "\u{0152}", - "\u{00D3}", - "\u{00D4}", - "\u{041E}", - "\u{0150}", - "\u{1D512}", - "\u{00D2}", - "\u{014C}", - "\u{03A9}", - "\u{039F}", - "\u{1D546}", - "\u{201C}", - "\u{2018}", - "\u{2A54}", - "\u{1D4AA}", - "\u{00D8}", - "\u{00D5}", - "\u{2A37}", - "\u{00D6}", - "\u{203E}", - "\u{23DE}", - "\u{23B4}", - "\u{23DC}", - "\u{2202}", - "\u{041F}", - "\u{1D513}", - "\u{03A6}", - "\u{03A0}", - "\u{00B1}", - "\u{210C}", - "\u{2119}", - "\u{2ABB}", - "\u{227A}", - "\u{2AAF}", - "\u{227C}", - "\u{227E}", - "\u{2033}", - "\u{220F}", - "\u{2237}", - "\u{221D}", - "\u{1D4AB}", - "\u{03A8}", - "\u{0022}", - "\u{1D514}", - "\u{211A}", - "\u{1D4AC}", - "\u{2910}", - "\u{00AE}", - "\u{0154}", - "\u{27EB}", - "\u{21A0}", - "\u{2916}", - "\u{0158}", - "\u{0156}", - "\u{0420}", - "\u{211C}", - "\u{220B}", - "\u{21CB}", - "\u{296F}", - "\u{211C}", - "\u{03A1}", - "\u{27E9}", - "\u{2192}", - "\u{21E5}", - "\u{21C4}", - "\u{2309}", - "\u{27E7}", - "\u{295D}", - "\u{21C2}", - "\u{2955}", - "\u{230B}", - "\u{22A2}", - "\u{21A6}", - "\u{295B}", - "\u{22B3}", - "\u{29D0}", - "\u{22B5}", - "\u{294F}", - "\u{295C}", - "\u{21BE}", - "\u{2954}", - "\u{21C0}", - "\u{2953}", - "\u{21D2}", - "\u{211D}", - "\u{2970}", - "\u{21DB}", - "\u{211B}", - "\u{21B1}", - "\u{29F4}", - "\u{0429}", - "\u{0428}", - "\u{042C}", - "\u{015A}", - "\u{2ABC}", - "\u{0160}", - "\u{015E}", - "\u{015C}", - "\u{0421}", - "\u{1D516}", - "\u{2193}", - "\u{2190}", - "\u{2192}", - "\u{2191}", - "\u{03A3}", - "\u{2218}", - "\u{1D54A}", - "\u{221A}", - "\u{25A1}", - "\u{2293}", - "\u{228F}", - "\u{2291}", - "\u{2290}", - "\u{2292}", - "\u{2294}", - "\u{1D4AE}", - "\u{22C6}", - "\u{22D0}", - "\u{22D0}", - "\u{2286}", - "\u{227B}", - "\u{2AB0}", - "\u{227D}", - "\u{227F}", - "\u{220B}", - "\u{2211}", - "\u{22D1}", - "\u{2283}", - "\u{2287}", - "\u{22D1}", - "\u{00DE}", - "\u{2122}", - "\u{040B}", - "\u{0426}", - "\u{0009}", - "\u{03A4}", - "\u{0164}", - "\u{0162}", - "\u{0422}", - "\u{1D517}", - "\u{2234}", - "\u{0398}", - "\u{205F}\u{200A}", - "\u{2009}", - "\u{223C}", - "\u{2243}", - "\u{2245}", - "\u{2248}", - "\u{1D54B}", - "\u{20DB}", - "\u{1D4AF}", - "\u{0166}", - "\u{00DA}", - "\u{219F}", - "\u{2949}", - "\u{040E}", - "\u{016C}", - "\u{00DB}", - "\u{0423}", - "\u{0170}", - "\u{1D518}", - "\u{00D9}", - "\u{016A}", - "\u{005F}", - "\u{23DF}", - "\u{23B5}", - "\u{23DD}", - "\u{22C3}", - "\u{228E}", - "\u{0172}", - "\u{1D54C}", - "\u{2191}", - "\u{2912}", - "\u{21C5}", - "\u{2195}", - "\u{296E}", - "\u{22A5}", - "\u{21A5}", - "\u{21D1}", - "\u{21D5}", - "\u{2196}", - "\u{2197}", - "\u{03D2}", - "\u{03A5}", - "\u{016E}", - "\u{1D4B0}", - "\u{0168}", - "\u{00DC}", - "\u{22AB}", - "\u{2AEB}", - "\u{0412}", - "\u{22A9}", - "\u{2AE6}", - "\u{22C1}", - "\u{2016}", - "\u{2016}", - "\u{2223}", - "\u{007C}", - "\u{2758}", - "\u{2240}", - "\u{200A}", - "\u{1D519}", - "\u{1D54D}", - "\u{1D4B1}", - "\u{22AA}", - "\u{0174}", - "\u{22C0}", - "\u{1D51A}", - "\u{1D54E}", - "\u{1D4B2}", - "\u{1D51B}", - "\u{039E}", - "\u{1D54F}", - "\u{1D4B3}", - "\u{042F}", - "\u{0407}", - "\u{042E}", - "\u{00DD}", - "\u{0176}", - "\u{042B}", - "\u{1D51C}", - "\u{1D550}", - "\u{1D4B4}", - "\u{0178}", - "\u{0416}", - "\u{0179}", - "\u{017D}", - "\u{0417}", - "\u{017B}", - "\u{200B}", - "\u{0396}", - "\u{2128}", - "\u{2124}", - "\u{1D4B5}", - "\u{00E1}", - "\u{0103}", - "\u{223E}", - "\u{223E}\u{0333}", - "\u{223F}", - "\u{00E2}", - "\u{00B4}", - "\u{0430}", - "\u{00E6}", - "\u{2061}", - "\u{1D51E}", - "\u{00E0}", - "\u{2135}", - "\u{2135}", - "\u{03B1}", - "\u{0101}", - "\u{2A3F}", - "\u{0026}", - "\u{2227}", - "\u{2A55}", - "\u{2A5C}", - "\u{2A58}", - "\u{2A5A}", - "\u{2220}", - "\u{29A4}", - "\u{2220}", - "\u{2221}", - "\u{29A8}", - "\u{29A9}", - "\u{29AA}", - "\u{29AB}", - "\u{29AC}", - "\u{29AD}", - "\u{29AE}", - "\u{29AF}", - "\u{221F}", - "\u{22BE}", - "\u{299D}", - "\u{2222}", - "\u{00C5}", - "\u{237C}", - "\u{0105}", - "\u{1D552}", - "\u{2248}", - "\u{2A70}", - "\u{2A6F}", - "\u{224A}", - "\u{224B}", - "\u{0027}", - "\u{2248}", - "\u{224A}", - "\u{00E5}", - "\u{1D4B6}", - "\u{002A}", - "\u{2248}", - "\u{224D}", - "\u{00E3}", - "\u{00E4}", - "\u{2233}", - "\u{2A11}", - "\u{2AED}", - "\u{224C}", - "\u{03F6}", - "\u{2035}", - "\u{223D}", - "\u{22CD}", - "\u{22BD}", - "\u{2305}", - "\u{2305}", - "\u{23B5}", - "\u{23B6}", - "\u{224C}", - "\u{0431}", - "\u{201E}", - "\u{2235}", - "\u{2235}", - "\u{29B0}", - "\u{03F6}", - "\u{212C}", - "\u{03B2}", - "\u{2136}", - "\u{226C}", - "\u{1D51F}", - "\u{22C2}", - "\u{25EF}", - "\u{22C3}", - "\u{2A00}", - "\u{2A01}", - "\u{2A02}", - "\u{2A06}", - "\u{2605}", - "\u{25BD}", - "\u{25B3}", - "\u{2A04}", - "\u{22C1}", - "\u{22C0}", - "\u{290D}", - "\u{29EB}", - "\u{25AA}", - "\u{25B4}", - "\u{25BE}", - "\u{25C2}", - "\u{25B8}", - "\u{2423}", - "\u{2592}", - "\u{2591}", - "\u{2593}", - "\u{2588}", - "\u{003D}\u{20E5}", - "\u{2261}\u{20E5}", - "\u{2310}", - "\u{1D553}", - "\u{22A5}", - "\u{22A5}", - "\u{22C8}", - "\u{2557}", - "\u{2554}", - "\u{2556}", - "\u{2553}", - "\u{2550}", - "\u{2566}", - "\u{2569}", - "\u{2564}", - "\u{2567}", - "\u{255D}", - "\u{255A}", - "\u{255C}", - "\u{2559}", - "\u{2551}", - "\u{256C}", - "\u{2563}", - "\u{2560}", - "\u{256B}", - "\u{2562}", - "\u{255F}", - "\u{29C9}", - "\u{2555}", - "\u{2552}", - "\u{2510}", - "\u{250C}", - "\u{2500}", - "\u{2565}", - "\u{2568}", - "\u{252C}", - "\u{2534}", - "\u{229F}", - "\u{229E}", - "\u{22A0}", - "\u{255B}", - "\u{2558}", - "\u{2518}", - "\u{2514}", - "\u{2502}", - "\u{256A}", - "\u{2561}", - "\u{255E}", - "\u{253C}", - "\u{2524}", - "\u{251C}", - "\u{2035}", - "\u{02D8}", - "\u{00A6}", - "\u{1D4B7}", - "\u{204F}", - "\u{223D}", - "\u{22CD}", - "\u{005C}", - "\u{29C5}", - "\u{27C8}", - "\u{2022}", - "\u{2022}", - "\u{224E}", - "\u{2AAE}", - "\u{224F}", - "\u{224F}", - "\u{0107}", - "\u{2229}", - "\u{2A44}", - "\u{2A49}", - "\u{2A4B}", - "\u{2A47}", - "\u{2A40}", - "\u{2229}\u{FE00}", - "\u{2041}", - "\u{02C7}", - "\u{2A4D}", - "\u{010D}", - "\u{00E7}", - "\u{0109}", - "\u{2A4C}", - "\u{2A50}", - "\u{010B}", - "\u{00B8}", - "\u{29B2}", - "\u{00A2}", - "\u{00B7}", - "\u{1D520}", - "\u{0447}", - "\u{2713}", - "\u{2713}", - "\u{03C7}", - "\u{25CB}", - "\u{29C3}", - "\u{02C6}", - "\u{2257}", - "\u{21BA}", - "\u{21BB}", - "\u{00AE}", - "\u{24C8}", - "\u{229B}", - "\u{229A}", - "\u{229D}", - "\u{2257}", - "\u{2A10}", - "\u{2AEF}", - "\u{29C2}", - "\u{2663}", - "\u{2663}", - "\u{003A}", - "\u{2254}", - "\u{2254}", - "\u{002C}", - "\u{0040}", - "\u{2201}", - "\u{2218}", - "\u{2201}", - "\u{2102}", - "\u{2245}", - "\u{2A6D}", - "\u{222E}", - "\u{1D554}", - "\u{2210}", - "\u{00A9}", - "\u{2117}", - "\u{21B5}", - "\u{2717}", - "\u{1D4B8}", - "\u{2ACF}", - "\u{2AD1}", - "\u{2AD0}", - "\u{2AD2}", - "\u{22EF}", - "\u{2938}", - "\u{2935}", - "\u{22DE}", - "\u{22DF}", - "\u{21B6}", - "\u{293D}", - "\u{222A}", - "\u{2A48}", - "\u{2A46}", - "\u{2A4A}", - "\u{228D}", - "\u{2A45}", - "\u{222A}\u{FE00}", - "\u{21B7}", - "\u{293C}", - "\u{22DE}", - "\u{22DF}", - "\u{22CE}", - "\u{22CF}", - "\u{00A4}", - "\u{21B6}", - "\u{21B7}", - "\u{22CE}", - "\u{22CF}", - "\u{2232}", - "\u{2231}", - "\u{232D}", - "\u{21D3}", - "\u{2965}", - "\u{2020}", - "\u{2138}", - "\u{2193}", - "\u{2010}", - "\u{22A3}", - "\u{290F}", - "\u{02DD}", - "\u{010F}", - "\u{0434}", - "\u{2146}", - "\u{2021}", - "\u{21CA}", - "\u{2A77}", - "\u{00B0}", - "\u{03B4}", - "\u{29B1}", - "\u{297F}", - "\u{1D521}", - "\u{21C3}", - "\u{21C2}", - "\u{22C4}", - "\u{22C4}", - "\u{2666}", - "\u{2666}", - "\u{00A8}", - "\u{03DD}", - "\u{22F2}", - "\u{00F7}", - "\u{00F7}", - "\u{22C7}", - "\u{22C7}", - "\u{0452}", - "\u{231E}", - "\u{230D}", - "\u{0024}", - "\u{1D555}", - "\u{02D9}", - "\u{2250}", - "\u{2251}", - "\u{2238}", - "\u{2214}", - "\u{22A1}", - "\u{2306}", - "\u{2193}", - "\u{21CA}", - "\u{21C3}", - "\u{21C2}", - "\u{2910}", - "\u{231F}", - "\u{230C}", - "\u{1D4B9}", - "\u{0455}", - "\u{29F6}", - "\u{0111}", - "\u{22F1}", - "\u{25BF}", - "\u{25BE}", - "\u{21F5}", - "\u{296F}", - "\u{29A6}", - "\u{045F}", - "\u{27FF}", - "\u{2A77}", - "\u{2251}", - "\u{00E9}", - "\u{2A6E}", - "\u{011B}", - "\u{2256}", - "\u{00EA}", - "\u{2255}", - "\u{044D}", - "\u{0117}", - "\u{2147}", - "\u{2252}", - "\u{1D522}", - "\u{2A9A}", - "\u{00E8}", - "\u{2A96}", - "\u{2A98}", - "\u{2A99}", - "\u{23E7}", - "\u{2113}", - "\u{2A95}", - "\u{2A97}", - "\u{0113}", - "\u{2205}", - "\u{2205}", - "\u{2205}", - "\u{2003}", - "\u{2004}", - "\u{2005}", - "\u{014B}", - "\u{2002}", - "\u{0119}", - "\u{1D556}", - "\u{22D5}", - "\u{29E3}", - "\u{2A71}", - "\u{03B5}", - "\u{03B5}", - "\u{03F5}", - "\u{2256}", - "\u{2255}", - "\u{2242}", - "\u{2A96}", - "\u{2A95}", - "\u{003D}", - "\u{225F}", - "\u{2261}", - "\u{2A78}", - "\u{29E5}", - "\u{2253}", - "\u{2971}", - "\u{212F}", - "\u{2250}", - "\u{2242}", - "\u{03B7}", - "\u{00F0}", - "\u{00EB}", - "\u{20AC}", - "\u{0021}", - "\u{2203}", - "\u{2130}", - "\u{2147}", - "\u{2252}", - "\u{0444}", - "\u{2640}", - "\u{FB03}", - "\u{FB00}", - "\u{FB04}", - "\u{1D523}", - "\u{FB01}", - "\u{0066}\u{006A}", - "\u{266D}", - "\u{FB02}", - "\u{25B1}", - "\u{0192}", - "\u{1D557}", - "\u{2200}", - "\u{22D4}", - "\u{2AD9}", - "\u{2A0D}", - "\u{00BD}", - "\u{2153}", - "\u{00BC}", - "\u{2155}", - "\u{2159}", - "\u{215B}", - "\u{2154}", - "\u{2156}", - "\u{00BE}", - "\u{2157}", - "\u{215C}", - "\u{2158}", - "\u{215A}", - "\u{215D}", - "\u{215E}", - "\u{2044}", - "\u{2322}", - "\u{1D4BB}", - "\u{2267}", - "\u{2A8C}", - "\u{01F5}", - "\u{03B3}", - "\u{03DD}", - "\u{2A86}", - "\u{011F}", - "\u{011D}", - "\u{0433}", - "\u{0121}", - "\u{2265}", - "\u{22DB}", - "\u{2265}", - "\u{2267}", - "\u{2A7E}", - "\u{2A7E}", - "\u{2AA9}", - "\u{2A80}", - "\u{2A82}", - "\u{2A84}", - "\u{22DB}\u{FE00}", - "\u{2A94}", - "\u{1D524}", - "\u{226B}", - "\u{22D9}", - "\u{2137}", - "\u{0453}", - "\u{2277}", - "\u{2A92}", - "\u{2AA5}", - "\u{2AA4}", - "\u{2269}", - "\u{2A8A}", - "\u{2A8A}", - "\u{2A88}", - "\u{2A88}", - "\u{2269}", - "\u{22E7}", - "\u{1D558}", - "\u{0060}", - "\u{210A}", - "\u{2273}", - "\u{2A8E}", - "\u{2A90}", - "\u{003E}", - "\u{2AA7}", - "\u{2A7A}", - "\u{22D7}", - "\u{2995}", - "\u{2A7C}", - "\u{2A86}", - "\u{2978}", - "\u{22D7}", - "\u{22DB}", - "\u{2A8C}", - "\u{2277}", - "\u{2273}", - "\u{2269}\u{FE00}", - "\u{2269}\u{FE00}", - "\u{21D4}", - "\u{200A}", - "\u{00BD}", - "\u{210B}", - "\u{044A}", - "\u{2194}", - "\u{2948}", - "\u{21AD}", - "\u{210F}", - "\u{0125}", - "\u{2665}", - "\u{2665}", - "\u{2026}", - "\u{22B9}", - "\u{1D525}", - "\u{2925}", - "\u{2926}", - "\u{21FF}", - "\u{223B}", - "\u{21A9}", - "\u{21AA}", - "\u{1D559}", - "\u{2015}", - "\u{1D4BD}", - "\u{210F}", - "\u{0127}", - "\u{2043}", - "\u{2010}", - "\u{00ED}", - "\u{2063}", - "\u{00EE}", - "\u{0438}", - "\u{0435}", - "\u{00A1}", - "\u{21D4}", - "\u{1D526}", - "\u{00EC}", - "\u{2148}", - "\u{2A0C}", - "\u{222D}", - "\u{29DC}", - "\u{2129}", - "\u{0133}", - "\u{012B}", - "\u{2111}", - "\u{2110}", - "\u{2111}", - "\u{0131}", - "\u{22B7}", - "\u{01B5}", - "\u{2208}", - "\u{2105}", - "\u{221E}", - "\u{29DD}", - "\u{0131}", - "\u{222B}", - "\u{22BA}", - "\u{2124}", - "\u{22BA}", - "\u{2A17}", - "\u{2A3C}", - "\u{0451}", - "\u{012F}", - "\u{1D55A}", - "\u{03B9}", - "\u{2A3C}", - "\u{00BF}", - "\u{1D4BE}", - "\u{2208}", - "\u{22F9}", - "\u{22F5}", - "\u{22F4}", - "\u{22F3}", - "\u{2208}", - "\u{2062}", - "\u{0129}", - "\u{0456}", - "\u{00EF}", - "\u{0135}", - "\u{0439}", - "\u{1D527}", - "\u{0237}", - "\u{1D55B}", - "\u{1D4BF}", - "\u{0458}", - "\u{0454}", - "\u{03BA}", - "\u{03F0}", - "\u{0137}", - "\u{043A}", - "\u{1D528}", - "\u{0138}", - "\u{0445}", - "\u{045C}", - "\u{1D55C}", - "\u{1D4C0}", - "\u{21DA}", - "\u{21D0}", - "\u{291B}", - "\u{290E}", - "\u{2266}", - "\u{2A8B}", - "\u{2962}", - "\u{013A}", - "\u{29B4}", - "\u{2112}", - "\u{03BB}", - "\u{27E8}", - "\u{2991}", - "\u{27E8}", - "\u{2A85}", - "\u{00AB}", - "\u{2190}", - "\u{21E4}", - "\u{291F}", - "\u{291D}", - "\u{21A9}", - "\u{21AB}", - "\u{2939}", - "\u{2973}", - "\u{21A2}", - "\u{2AAB}", - "\u{2919}", - "\u{2AAD}", - "\u{2AAD}\u{FE00}", - "\u{290C}", - "\u{2772}", - "\u{007B}", - "\u{005B}", - "\u{298B}", - "\u{298F}", - "\u{298D}", - "\u{013E}", - "\u{013C}", - "\u{2308}", - "\u{007B}", - "\u{043B}", - "\u{2936}", - "\u{201C}", - "\u{201E}", - "\u{2967}", - "\u{294B}", - "\u{21B2}", - "\u{2264}", - "\u{2190}", - "\u{21A2}", - "\u{21BD}", - "\u{21BC}", - "\u{21C7}", - "\u{2194}", - "\u{21C6}", - "\u{21CB}", - "\u{21AD}", - "\u{22CB}", - "\u{22DA}", - "\u{2264}", - "\u{2266}", - "\u{2A7D}", - "\u{2A7D}", - "\u{2AA8}", - "\u{2A7F}", - "\u{2A81}", - "\u{2A83}", - "\u{22DA}\u{FE00}", - "\u{2A93}", - "\u{2A85}", - "\u{22D6}", - "\u{22DA}", - "\u{2A8B}", - "\u{2276}", - "\u{2272}", - "\u{297C}", - "\u{230A}", - "\u{1D529}", - "\u{2276}", - "\u{2A91}", - "\u{21BD}", - "\u{21BC}", - "\u{296A}", - "\u{2584}", - "\u{0459}", - "\u{226A}", - "\u{21C7}", - "\u{231E}", - "\u{296B}", - "\u{25FA}", - "\u{0140}", - "\u{23B0}", - "\u{23B0}", - "\u{2268}", - "\u{2A89}", - "\u{2A89}", - "\u{2A87}", - "\u{2A87}", - "\u{2268}", - "\u{22E6}", - "\u{27EC}", - "\u{21FD}", - "\u{27E6}", - "\u{27F5}", - "\u{27F7}", - "\u{27FC}", - "\u{27F6}", - "\u{21AB}", - "\u{21AC}", - "\u{2985}", - "\u{1D55D}", - "\u{2A2D}", - "\u{2A34}", - "\u{2217}", - "\u{005F}", - "\u{25CA}", - "\u{25CA}", - "\u{29EB}", - "\u{0028}", - "\u{2993}", - "\u{21C6}", - "\u{231F}", - "\u{21CB}", - "\u{296D}", - "\u{200E}", - "\u{22BF}", - "\u{2039}", - "\u{1D4C1}", - "\u{21B0}", - "\u{2272}", - "\u{2A8D}", - "\u{2A8F}", - "\u{005B}", - "\u{2018}", - "\u{201A}", - "\u{0142}", - "\u{003C}", - "\u{2AA6}", - "\u{2A79}", - "\u{22D6}", - "\u{22CB}", - "\u{22C9}", - "\u{2976}", - "\u{2A7B}", - "\u{2996}", - "\u{25C3}", - "\u{22B4}", - "\u{25C2}", - "\u{294A}", - "\u{2966}", - "\u{2268}\u{FE00}", - "\u{2268}\u{FE00}", - "\u{223A}", - "\u{00AF}", - "\u{2642}", - "\u{2720}", - "\u{2720}", - "\u{21A6}", - "\u{21A6}", - "\u{21A7}", - "\u{21A4}", - "\u{21A5}", - "\u{25AE}", - "\u{2A29}", - "\u{043C}", - "\u{2014}", - "\u{2221}", - "\u{1D52A}", - "\u{2127}", - "\u{00B5}", - "\u{2223}", - "\u{002A}", - "\u{2AF0}", - "\u{00B7}", - "\u{2212}", - "\u{229F}", - "\u{2238}", - "\u{2A2A}", - "\u{2ADB}", - "\u{2026}", - "\u{2213}", - "\u{22A7}", - "\u{1D55E}", - "\u{2213}", - "\u{1D4C2}", - "\u{223E}", - "\u{03BC}", - "\u{22B8}", - "\u{22B8}", - "\u{22D9}\u{0338}", - "\u{226B}\u{20D2}", - "\u{226B}\u{0338}", - "\u{21CD}", - "\u{21CE}", - "\u{22D8}\u{0338}", - "\u{226A}\u{20D2}", - "\u{226A}\u{0338}", - "\u{21CF}", - "\u{22AF}", - "\u{22AE}", - "\u{2207}", - "\u{0144}", - "\u{2220}\u{20D2}", - "\u{2249}", - "\u{2A70}\u{0338}", - "\u{224B}\u{0338}", - "\u{0149}", - "\u{2249}", - "\u{266E}", - "\u{266E}", - "\u{2115}", - "\u{00A0}", - "\u{224E}\u{0338}", - "\u{224F}\u{0338}", - "\u{2A43}", - "\u{0148}", - "\u{0146}", - "\u{2247}", - "\u{2A6D}\u{0338}", - "\u{2A42}", - "\u{043D}", - "\u{2013}", - "\u{2260}", - "\u{21D7}", - "\u{2924}", - "\u{2197}", - "\u{2197}", - "\u{2250}\u{0338}", - "\u{2262}", - "\u{2928}", - "\u{2242}\u{0338}", - "\u{2204}", - "\u{2204}", - "\u{1D52B}", - "\u{2267}\u{0338}", - "\u{2271}", - "\u{2271}", - "\u{2267}\u{0338}", - "\u{2A7E}\u{0338}", - "\u{2A7E}\u{0338}", - "\u{2275}", - "\u{226F}", - "\u{226F}", - "\u{21CE}", - "\u{21AE}", - "\u{2AF2}", - "\u{220B}", - "\u{22FC}", - "\u{22FA}", - "\u{220B}", - "\u{045A}", - "\u{21CD}", - "\u{2266}\u{0338}", - "\u{219A}", - "\u{2025}", - "\u{2270}", - "\u{219A}", - "\u{21AE}", - "\u{2270}", - "\u{2266}\u{0338}", - "\u{2A7D}\u{0338}", - "\u{2A7D}\u{0338}", - "\u{226E}", - "\u{2274}", - "\u{226E}", - "\u{22EA}", - "\u{22EC}", - "\u{2224}", - "\u{1D55F}", - "\u{00AC}", - "\u{2209}", - "\u{22F9}\u{0338}", - "\u{22F5}\u{0338}", - "\u{2209}", - "\u{22F7}", - "\u{22F6}", - "\u{220C}", - "\u{220C}", - "\u{22FE}", - "\u{22FD}", - "\u{2226}", - "\u{2226}", - "\u{2AFD}\u{20E5}", - "\u{2202}\u{0338}", - "\u{2A14}", - "\u{2280}", - "\u{22E0}", - "\u{2AAF}\u{0338}", - "\u{2280}", - "\u{2AAF}\u{0338}", - "\u{21CF}", - "\u{219B}", - "\u{2933}\u{0338}", - "\u{219D}\u{0338}", - "\u{219B}", - "\u{22EB}", - "\u{22ED}", - "\u{2281}", - "\u{22E1}", - "\u{2AB0}\u{0338}", - "\u{1D4C3}", - "\u{2224}", - "\u{2226}", - "\u{2241}", - "\u{2244}", - "\u{2244}", - "\u{2224}", - "\u{2226}", - "\u{22E2}", - "\u{22E3}", - "\u{2284}", - "\u{2AC5}\u{0338}", - "\u{2288}", - "\u{2282}\u{20D2}", - "\u{2288}", - "\u{2AC5}\u{0338}", - "\u{2281}", - "\u{2AB0}\u{0338}", - "\u{2285}", - "\u{2AC6}\u{0338}", - "\u{2289}", - "\u{2283}\u{20D2}", - "\u{2289}", - "\u{2AC6}\u{0338}", - "\u{2279}", - "\u{00F1}", - "\u{2278}", - "\u{22EA}", - "\u{22EC}", - "\u{22EB}", - "\u{22ED}", - "\u{03BD}", - "\u{0023}", - "\u{2116}", - "\u{2007}", - "\u{22AD}", - "\u{2904}", - "\u{224D}\u{20D2}", - "\u{22AC}", - "\u{2265}\u{20D2}", - "\u{003E}\u{20D2}", - "\u{29DE}", - "\u{2902}", - "\u{2264}\u{20D2}", - "\u{003C}\u{20D2}", - "\u{22B4}\u{20D2}", - "\u{2903}", - "\u{22B5}\u{20D2}", - "\u{223C}\u{20D2}", - "\u{21D6}", - "\u{2923}", - "\u{2196}", - "\u{2196}", - "\u{2927}", - "\u{24C8}", - "\u{00F3}", - "\u{229B}", - "\u{229A}", - "\u{00F4}", - "\u{043E}", - "\u{229D}", - "\u{0151}", - "\u{2A38}", - "\u{2299}", - "\u{29BC}", - "\u{0153}", - "\u{29BF}", - "\u{1D52C}", - "\u{02DB}", - "\u{00F2}", - "\u{29C1}", - "\u{29B5}", - "\u{03A9}", - "\u{222E}", - "\u{21BA}", - "\u{29BE}", - "\u{29BB}", - "\u{203E}", - "\u{29C0}", - "\u{014D}", - "\u{03C9}", - "\u{03BF}", - "\u{29B6}", - "\u{2296}", - "\u{1D560}", - "\u{29B7}", - "\u{29B9}", - "\u{2295}", - "\u{2228}", - "\u{21BB}", - "\u{2A5D}", - "\u{2134}", - "\u{2134}", - "\u{00AA}", - "\u{00BA}", - "\u{22B6}", - "\u{2A56}", - "\u{2A57}", - "\u{2A5B}", - "\u{2134}", - "\u{00F8}", - "\u{2298}", - "\u{00F5}", - "\u{2297}", - "\u{2A36}", - "\u{00F6}", - "\u{233D}", - "\u{2225}", - "\u{00B6}", - "\u{2225}", - "\u{2AF3}", - "\u{2AFD}", - "\u{2202}", - "\u{043F}", - "\u{0025}", - "\u{002E}", - "\u{2030}", - "\u{22A5}", - "\u{2031}", - "\u{1D52D}", - "\u{03C6}", - "\u{03D5}", - "\u{2133}", - "\u{260E}", - "\u{03C0}", - "\u{22D4}", - "\u{03D6}", - "\u{210F}", - "\u{210E}", - "\u{210F}", - "\u{002B}", - "\u{2A23}", - "\u{229E}", - "\u{2A22}", - "\u{2214}", - "\u{2A25}", - "\u{2A72}", - "\u{00B1}", - "\u{2A26}", - "\u{2A27}", - "\u{00B1}", - "\u{2A15}", - "\u{1D561}", - "\u{00A3}", - "\u{227A}", - "\u{2AB3}", - "\u{2AB7}", - "\u{227C}", - "\u{2AAF}", - "\u{227A}", - "\u{2AB7}", - "\u{227C}", - "\u{2AAF}", - "\u{2AB9}", - "\u{2AB5}", - "\u{22E8}", - "\u{227E}", - "\u{2032}", - "\u{2119}", - "\u{2AB5}", - "\u{2AB9}", - "\u{22E8}", - "\u{220F}", - "\u{232E}", - "\u{2312}", - "\u{2313}", - "\u{221D}", - "\u{221D}", - "\u{227E}", - "\u{22B0}", - "\u{1D4C5}", - "\u{03C8}", - "\u{2008}", - "\u{1D52E}", - "\u{2A0C}", - "\u{1D562}", - "\u{2057}", - "\u{1D4C6}", - "\u{210D}", - "\u{2A16}", - "\u{003F}", - "\u{225F}", - "\u{0022}", - "\u{21DB}", - "\u{21D2}", - "\u{291C}", - "\u{290F}", - "\u{2964}", - "\u{223D}\u{0331}", - "\u{0155}", - "\u{221A}", - "\u{29B3}", - "\u{27E9}", - "\u{2992}", - "\u{29A5}", - "\u{27E9}", - "\u{00BB}", - "\u{2192}", - "\u{2975}", - "\u{21E5}", - "\u{2920}", - "\u{2933}", - "\u{291E}", - "\u{21AA}", - "\u{21AC}", - "\u{2945}", - "\u{2974}", - "\u{21A3}", - "\u{219D}", - "\u{291A}", - "\u{2236}", - "\u{211A}", - "\u{290D}", - "\u{2773}", - "\u{007D}", - "\u{005D}", - "\u{298C}", - "\u{298E}", - "\u{2990}", - "\u{0159}", - "\u{0157}", - "\u{2309}", - "\u{007D}", - "\u{0440}", - "\u{2937}", - "\u{2969}", - "\u{201D}", - "\u{201D}", - "\u{21B3}", - "\u{211C}", - "\u{211B}", - "\u{211C}", - "\u{211D}", - "\u{25AD}", - "\u{00AE}", - "\u{297D}", - "\u{230B}", - "\u{1D52F}", - "\u{21C1}", - "\u{21C0}", - "\u{296C}", - "\u{03C1}", - "\u{03F1}", - "\u{2192}", - "\u{21A3}", - "\u{21C1}", - "\u{21C0}", - "\u{21C4}", - "\u{21CC}", - "\u{21C9}", - "\u{219D}", - "\u{22CC}", - "\u{02DA}", - "\u{2253}", - "\u{21C4}", - "\u{21CC}", - "\u{200F}", - "\u{23B1}", - "\u{23B1}", - "\u{2AEE}", - "\u{27ED}", - "\u{21FE}", - "\u{27E7}", - "\u{2986}", - "\u{1D563}", - "\u{2A2E}", - "\u{2A35}", - "\u{0029}", - "\u{2994}", - "\u{2A12}", - "\u{21C9}", - "\u{203A}", - "\u{1D4C7}", - "\u{21B1}", - "\u{005D}", - "\u{2019}", - "\u{2019}", - "\u{22CC}", - "\u{22CA}", - "\u{25B9}", - "\u{22B5}", - "\u{25B8}", - "\u{29CE}", - "\u{2968}", - "\u{211E}", - "\u{015B}", - "\u{201A}", - "\u{227B}", - "\u{2AB4}", - "\u{2AB8}", - "\u{0161}", - "\u{227D}", - "\u{2AB0}", - "\u{015F}", - "\u{015D}", - "\u{2AB6}", - "\u{2ABA}", - "\u{22E9}", - "\u{2A13}", - "\u{227F}", - "\u{0441}", - "\u{22C5}", - "\u{22A1}", - "\u{2A66}", - "\u{21D8}", - "\u{2925}", - "\u{2198}", - "\u{2198}", - "\u{00A7}", - "\u{003B}", - "\u{2929}", - "\u{2216}", - "\u{2216}", - "\u{2736}", - "\u{1D530}", - "\u{2322}", - "\u{266F}", - "\u{0449}", - "\u{0448}", - "\u{2223}", - "\u{2225}", - "\u{00AD}", - "\u{03C3}", - "\u{03C2}", - "\u{03C2}", - "\u{223C}", - "\u{2A6A}", - "\u{2243}", - "\u{2243}", - "\u{2A9E}", - "\u{2AA0}", - "\u{2A9D}", - "\u{2A9F}", - "\u{2246}", - "\u{2A24}", - "\u{2972}", - "\u{2190}", - "\u{2216}", - "\u{2A33}", - "\u{29E4}", - "\u{2223}", - "\u{2323}", - "\u{2AAA}", - "\u{2AAC}", - "\u{2AAC}\u{FE00}", - "\u{044C}", - "\u{002F}", - "\u{29C4}", - "\u{233F}", - "\u{1D564}", - "\u{2660}", - "\u{2660}", - "\u{2225}", - "\u{2293}", - "\u{2293}\u{FE00}", - "\u{2294}", - "\u{2294}\u{FE00}", - "\u{228F}", - "\u{2291}", - "\u{228F}", - "\u{2291}", - "\u{2290}", - "\u{2292}", - "\u{2290}", - "\u{2292}", - "\u{25A1}", - "\u{25A1}", - "\u{25AA}", - "\u{25AA}", - "\u{2192}", - "\u{1D4C8}", - "\u{2216}", - "\u{2323}", - "\u{22C6}", - "\u{2606}", - "\u{2605}", - "\u{03F5}", - "\u{03D5}", - "\u{00AF}", - "\u{2282}", - "\u{2AC5}", - "\u{2ABD}", - "\u{2286}", - "\u{2AC3}", - "\u{2AC1}", - "\u{2ACB}", - "\u{228A}", - "\u{2ABF}", - "\u{2979}", - "\u{2282}", - "\u{2286}", - "\u{2AC5}", - "\u{228A}", - "\u{2ACB}", - "\u{2AC7}", - "\u{2AD5}", - "\u{2AD3}", - "\u{227B}", - "\u{2AB8}", - "\u{227D}", - "\u{2AB0}", - "\u{2ABA}", - "\u{2AB6}", - "\u{22E9}", - "\u{227F}", - "\u{2211}", - "\u{266A}", - "\u{2283}", - "\u{00B9}", - "\u{00B2}", - "\u{00B3}", - "\u{2AC6}", - "\u{2ABE}", - "\u{2AD8}", - "\u{2287}", - "\u{2AC4}", - "\u{27C9}", - "\u{2AD7}", - "\u{297B}", - "\u{2AC2}", - "\u{2ACC}", - "\u{228B}", - "\u{2AC0}", - "\u{2283}", - "\u{2287}", - "\u{2AC6}", - "\u{228B}", - "\u{2ACC}", - "\u{2AC8}", - "\u{2AD4}", - "\u{2AD6}", - "\u{21D9}", - "\u{2926}", - "\u{2199}", - "\u{2199}", - "\u{292A}", - "\u{00DF}", - "\u{2316}", - "\u{03C4}", - "\u{23B4}", - "\u{0165}", - "\u{0163}", - "\u{0442}", - "\u{20DB}", - "\u{2315}", - "\u{1D531}", - "\u{2234}", - "\u{2234}", - "\u{03B8}", - "\u{03D1}", - "\u{03D1}", - "\u{2248}", - "\u{223C}", - "\u{2009}", - "\u{2248}", - "\u{223C}", - "\u{00FE}", - "\u{02DC}", - "\u{00D7}", - "\u{22A0}", - "\u{2A31}", - "\u{2A30}", - "\u{222D}", - "\u{2928}", - "\u{22A4}", - "\u{2336}", - "\u{2AF1}", - "\u{1D565}", - "\u{2ADA}", - "\u{2929}", - "\u{2034}", - "\u{2122}", - "\u{25B5}", - "\u{25BF}", - "\u{25C3}", - "\u{22B4}", - "\u{225C}", - "\u{25B9}", - "\u{22B5}", - "\u{25EC}", - "\u{225C}", - "\u{2A3A}", - "\u{2A39}", - "\u{29CD}", - "\u{2A3B}", - "\u{23E2}", - "\u{1D4C9}", - "\u{0446}", - "\u{045B}", - "\u{0167}", - "\u{226C}", - "\u{219E}", - "\u{21A0}", - "\u{21D1}", - "\u{2963}", - "\u{00FA}", - "\u{2191}", - "\u{045E}", - "\u{016D}", - "\u{00FB}", - "\u{0443}", - "\u{21C5}", - "\u{0171}", - "\u{296E}", - "\u{297E}", - "\u{1D532}", - "\u{00F9}", - "\u{21BF}", - "\u{21BE}", - "\u{2580}", - "\u{231C}", - "\u{231C}", - "\u{230F}", - "\u{25F8}", - "\u{016B}", - "\u{00A8}", - "\u{0173}", - "\u{1D566}", - "\u{2191}", - "\u{2195}", - "\u{21BF}", - "\u{21BE}", - "\u{228E}", - "\u{03C5}", - "\u{03D2}", - "\u{03C5}", - "\u{21C8}", - "\u{231D}", - "\u{231D}", - "\u{230E}", - "\u{016F}", - "\u{25F9}", - "\u{1D4CA}", - "\u{22F0}", - "\u{0169}", - "\u{25B5}", - "\u{25B4}", - "\u{21C8}", - "\u{00FC}", - "\u{29A7}", - "\u{21D5}", - "\u{2AE8}", - "\u{2AE9}", - "\u{22A8}", - "\u{299C}", - "\u{03F5}", - "\u{03F0}", - "\u{2205}", - "\u{03D5}", - "\u{03D6}", - "\u{221D}", - "\u{2195}", - "\u{03F1}", - "\u{03C2}", - "\u{228A}\u{FE00}", - "\u{2ACB}\u{FE00}", - "\u{228B}\u{FE00}", - "\u{2ACC}\u{FE00}", - "\u{03D1}", - "\u{22B2}", - "\u{22B3}", - "\u{0432}", - "\u{22A2}", - "\u{2228}", - "\u{22BB}", - "\u{225A}", - "\u{22EE}", - "\u{007C}", - "\u{007C}", - "\u{1D533}", - "\u{22B2}", - "\u{2282}\u{20D2}", - "\u{2283}\u{20D2}", - "\u{1D567}", - "\u{221D}", - "\u{22B3}", - "\u{1D4CB}", - "\u{2ACB}\u{FE00}", - "\u{228A}\u{FE00}", - "\u{2ACC}\u{FE00}", - "\u{228B}\u{FE00}", - "\u{299A}", - "\u{0175}", - "\u{2A5F}", - "\u{2227}", - "\u{2259}", - "\u{2118}", - "\u{1D534}", - "\u{1D568}", - "\u{2118}", - "\u{2240}", - "\u{2240}", - "\u{1D4CC}", - "\u{22C2}", - "\u{25EF}", - "\u{22C3}", - "\u{25BD}", - "\u{1D535}", - "\u{27FA}", - "\u{27F7}", - "\u{03BE}", - "\u{27F8}", - "\u{27F5}", - "\u{27FC}", - "\u{22FB}", - "\u{2A00}", - "\u{1D569}", - "\u{2A01}", - "\u{2A02}", - "\u{27F9}", - "\u{27F6}", - "\u{1D4CD}", - "\u{2A06}", - "\u{2A04}", - "\u{25B3}", - "\u{22C1}", - "\u{22C0}", - "\u{00FD}", - "\u{044F}", - "\u{0177}", - "\u{044B}", - "\u{00A5}", - "\u{1D536}", - "\u{0457}", - "\u{1D56A}", - "\u{1D4CE}", - "\u{044E}", - "\u{00FF}", - "\u{017A}", - "\u{017E}", - "\u{0437}", - "\u{017C}", - "\u{2128}", - "\u{03B6}", - "\u{1D537}", - "\u{0436}", - "\u{21DD}", - "\u{1D56B}", - "\u{1D4CF}", - "\u{200D}", - "\u{200C}", - ]; - -pub fn get_entity(name: &str) -> Option<&'static str> { - ENTITIES.binary_search(&name).ok().map(|i| ENTITY_VALUES[i]) -} - diff --git a/vendor/pulldown-cmark-0.1.2/src/escape.rs b/vendor/pulldown-cmark-0.1.2/src/escape.rs deleted file mode 100644 index fd0d901ce1..0000000000 --- a/vendor/pulldown-cmark-0.1.2/src/escape.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Utility functions for HTML escaping - -use std::str::from_utf8; - -static HREF_SAFE: [u8; 128] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - ]; - -static HEX_CHARS: &'static [u8] = b"0123456789ABCDEF"; - -pub fn escape_href(ob: &mut String, s: &str) { - let mut mark = 0; - for i in 0..s.len() { - let c = s.as_bytes()[i]; - if c >= 0x80 || HREF_SAFE[c as usize] == 0 { - // character needing escape - - // write partial substring up to mark - if mark < i { - ob.push_str(&s[mark..i]); - } - match c { - b'&' => { - ob.push_str("&"); - }, - b'\'' => { - ob.push_str("'"); - }, - _ => { - let mut buf = [0u8; 3]; - buf[0] = b'%'; - buf[1] = HEX_CHARS[((c as usize) >> 4) & 0xF]; - buf[2] = HEX_CHARS[(c as usize) & 0xF]; - ob.push_str(from_utf8(&buf).unwrap()); - } - } - mark = i + 1; // all escaped characters are ASCII - } - } - ob.push_str(&s[mark..]); -} - -static HTML_ESCAPE_TABLE: [u8; 256] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - -static HTML_ESCAPES: [&'static str; 6] = [ - "", - """, - "&", - "/", - "<", - ">" - ]; - -pub fn escape_html(ob: &mut String, s: &str, secure: bool) { - let size = s.len(); - let bytes = s.as_bytes(); - let mut mark = 0; - let mut i = 0; - while i < size { - match bytes[i..].iter().position(|&c| HTML_ESCAPE_TABLE[c as usize] != 0) { - Some(pos) => { - i += pos; - } - None => break - } - let c = bytes[i]; - let escape = HTML_ESCAPE_TABLE[c as usize]; - if escape != 0 && (secure || c != b'/') { - ob.push_str(&s[mark..i]); - ob.push_str(HTML_ESCAPES[escape as usize]); - mark = i + 1; // all escaped characters are ASCII - } - i += 1; - } - ob.push_str(&s[mark..]); -} diff --git a/vendor/pulldown-cmark-0.1.2/src/html.rs b/vendor/pulldown-cmark-0.1.2/src/html.rs deleted file mode 100644 index 0635132958..0000000000 --- a/vendor/pulldown-cmark-0.1.2/src/html.rs +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! HTML renderer that takes an iterator of events as input. - -use std::borrow::Cow; -use std::collections::HashMap; -use std::fmt::Write; - -use parse::{Event, Tag}; -use parse::Event::{Start, End, Text, Html, InlineHtml, SoftBreak, HardBreak, FootnoteReference}; -use parse::Alignment; -use escape::{escape_html, escape_href}; - -enum TableState { - Head, - Body, -} - -struct Ctx<'b, I> { - iter: I, - buf: &'b mut String, - table_state: TableState, - table_alignments: Vec, - table_cell_index: usize, -} - -impl<'a, 'b, I: Iterator>> Ctx<'b, I> { - fn fresh_line(&mut self) { - if !(self.buf.is_empty() || self.buf.ends_with('\n')) { - self.buf.push('\n'); - } - } - - pub fn run(&mut self) { - let mut numbers = HashMap::new(); - while let Some(event) = self.iter.next() { - match event { - Start(tag) => self.start_tag(tag, &mut numbers), - End(tag) => self.end_tag(tag), - Text(text) => escape_html(self.buf, &text, false), - Html(html) | - InlineHtml(html) => self.buf.push_str(&html), - SoftBreak => self.buf.push('\n'), - HardBreak => self.buf.push_str("
    \n"), - FootnoteReference(name) => { - let len = numbers.len() + 1; - self.buf.push_str(""); - let number = numbers.entry(name).or_insert(len); - self.buf.push_str(&*format!("{}", number)); - self.buf.push_str(""); - }, - } - } - } - - fn start_tag(&mut self, tag: Tag<'a>, numbers: &mut HashMap, usize>) { - match tag { - Tag::Paragraph => { - self.fresh_line(); - self.buf.push_str("

    "); - } - Tag::Rule => { - self.fresh_line(); - self.buf.push_str("


    \n") - } - Tag::Header(level) => { - self.fresh_line(); - self.buf.push_str("'); - } - Tag::Table(alignments) => { - self.table_alignments = alignments; - self.buf.push_str(""); - } - Tag::TableHead => { - self.table_state = TableState::Head; - self.buf.push_str(""); - } - Tag::TableRow => { - self.table_cell_index = 0; - self.buf.push_str(""); - } - Tag::TableCell => { - match self.table_state { - TableState::Head => self.buf.push_str(" self.buf.push_str(" self.buf.push_str(" align=\"left\""), - Some(&Alignment::Center) => self.buf.push_str(" align=\"center\""), - Some(&Alignment::Right) => self.buf.push_str(" align=\"right\""), - _ => (), - } - self.buf.push_str(">"); - } - Tag::BlockQuote => { - self.fresh_line(); - self.buf.push_str("
    \n"); - } - Tag::CodeBlock(info) => { - self.fresh_line(); - let lang = info.split(' ').next().unwrap(); - if lang.is_empty() { - self.buf.push_str("
    ");
    -                } else {
    -                    self.buf.push_str("
    ");
    -                }
    -            }
    -            Tag::List(Some(1)) => {
    -                self.fresh_line();
    -                self.buf.push_str("
      \n"); - } - Tag::List(Some(start)) => { - self.fresh_line(); - let _ = write!(self.buf, "
        \n", start); - } - Tag::List(None) => { - self.fresh_line(); - self.buf.push_str("
    \n"); - } - Tag::TableHead => { - self.buf.push_str("\n"); - self.table_state = TableState::Body; - } - Tag::TableRow => { - self.buf.push_str("\n"); - } - Tag::TableCell => { - match self.table_state { - TableState::Head => self.buf.push_str(""), - TableState::Body => self.buf.push_str(""), - } - self.table_cell_index += 1; - } - Tag::BlockQuote => self.buf.push_str("\n"), - Tag::CodeBlock(_) => self.buf.push_str("\n"), - Tag::List(Some(_)) => self.buf.push_str("\n"), - Tag::List(None) => self.buf.push_str("\n"), - Tag::Item => self.buf.push_str("
  • \n"), - Tag::Emphasis => self.buf.push_str(""), - Tag::Strong => self.buf.push_str(""), - Tag::Code => self.buf.push_str(""), - Tag::Link(_, _) => self.buf.push_str(""), - Tag::Image(_, _) => (), // shouldn't happen, handled in start - Tag::FootnoteDefinition(_) => self.buf.push_str("
    \n"), - } - } - - // run raw text, consuming end tag - fn raw_text<'c>(&mut self, numbers: &'c mut HashMap, usize>) { - let mut nest = 0; - while let Some(event) = self.iter.next() { - match event { - Start(_) => nest += 1, - End(_) => { - if nest == 0 { break; } - nest -= 1; - } - Text(text) => escape_html(self.buf, &text, false), - Html(_) => (), - InlineHtml(html) => escape_html(self.buf, &html, false), - SoftBreak | HardBreak => self.buf.push(' '), - FootnoteReference(name) => { - let len = numbers.len() + 1; - let number = numbers.entry(name).or_insert(len); - self.buf.push_str(&*format!("[{}]", number)); - } - } - } - } -} - -/// Iterate over an `Iterator` of `Event`s, generate HTML for each `Event`, and -/// push it to a `String`. -/// -/// # Examples -/// -/// ``` -/// use pulldown_cmark::{html, Parser}; -/// -/// let markdown_str = r#" -/// hello -/// ===== -/// -/// * alpha -/// * beta -/// "#; -/// let parser = Parser::new(markdown_str); -/// -/// let mut html_buf = String::new(); -/// html::push_html(&mut html_buf, parser); -/// -/// assert_eq!(html_buf, r#"

    hello

    -///
      -///
    • alpha
    • -///
    • beta
    • -///
    -/// "#); -/// ``` -pub fn push_html<'a, I: Iterator>>(buf: &mut String, iter: I) { - let mut ctx = Ctx { - iter: iter, - buf: buf, - table_state: TableState::Head, - table_alignments: vec![], - table_cell_index: 0, - }; - ctx.run(); -} diff --git a/vendor/pulldown-cmark-0.1.2/src/lib.rs b/vendor/pulldown-cmark-0.1.2/src/lib.rs deleted file mode 100644 index de7ac57c89..0000000000 --- a/vendor/pulldown-cmark-0.1.2/src/lib.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Pull parser for commonmark. - -// When compiled for the rustc compiler itself we want to make sure that this is -// an unstable crate. -#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] -#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] - -pub mod html; - -#[macro_use] -extern crate bitflags; - -mod passes; -mod parse; -mod scanners; -mod entities; -mod escape; -mod puncttable; -mod utils; - -pub use passes::Parser; -pub use parse::{Alignment, Event, Tag, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; diff --git a/vendor/pulldown-cmark-0.1.2/src/main.rs b/vendor/pulldown-cmark-0.1.2/src/main.rs deleted file mode 100644 index 5a83484777..0000000000 --- a/vendor/pulldown-cmark-0.1.2/src/main.rs +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Command line tool to exercise pulldown-cmark. - -extern crate getopts; - -extern crate pulldown_cmark; - -use pulldown_cmark::Parser; -use pulldown_cmark::{Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES}; -use pulldown_cmark::html; - -use std::env; -use std::io; -use std::io::{Read, Write}; -use std::path::Path; -use std::fs::File; - -fn render_html(text: &str, opts: Options) -> String { - let mut s = String::with_capacity(text.len() * 3 / 2); - let p = Parser::new_ext(text, opts); - html::push_html(&mut s, p); - s -} - -fn dry_run(text:&str, opts: Options) { - let p = Parser::new_ext(text, opts); - /* - let events = p.collect::>(); - let count = events.len(); - */ - let count = p.count(); - println!("{} events", count); -} - -fn print_events(text: &str, opts: Options) { - let mut p = Parser::new_ext(text, opts); - loop { - print!("{}: ", p.get_offset()); - if let Some(event) = p.next() { - println!("{:?}", event); - } else { - break; - } - } - println!("EOF"); -} - -fn read_file(filename: &str) -> String { - let path = Path::new(filename); - let mut file = match File::open(&path) { - Err(why) => panic!("couldn't open {}: {}", path.display(), why), - Ok(file) => file - }; - let mut s = String::new(); - match file.read_to_string(&mut s) { - Err(why) => panic!("couldn't open {}: {}", path.display(), why), - Ok(_) => s - } -} - -// Tests in the spec (v0.26) are of the form: -// -// ```````````````````````````````` example -// -// . -// -// ```````````````````````````````` -struct Spec<'a> { - spec: &'a str, - test_n: usize, -} - -impl<'a> Spec<'a> { - pub fn new(spec: &'a str) -> Self { - Spec{ spec: spec, test_n: 0 } - } -} - -struct TestCase<'a> { - n: usize, - input: &'a str, - expected: &'a str, -} - -impl<'a> TestCase<'a> { - pub fn new(n: usize, input: &'a str, expected: &'a str) -> Self { - TestCase { n: n, input: input, expected: expected } - } -} - -impl<'a> Iterator for Spec<'a> { - type Item = TestCase<'a>; - - fn next(&mut self) -> Option> { - let spec = self.spec; - - let i_start = match self.spec.find("```````````````````````````````` example\n").map(|pos| pos + 41) { - Some(pos) => pos, - None => return None, - }; - - let i_end = match self.spec[i_start..].find("\n.\n").map(|pos| (pos + 1) + i_start){ - Some(pos) => pos, - None => return None, - }; - - let e_end = match self.spec[i_end + 2..].find("````````````````````````````````\n").map(|pos| pos + i_end + 2){ - Some(pos) => pos, - None => return None, - }; - - self.test_n += 1; - self.spec = &self.spec[e_end + 33 ..]; - - Some(TestCase::new(self.test_n, &spec[i_start .. i_end], &spec[i_end + 2 .. e_end])) - } -} - - -fn run_spec(spec_text: &str, args: &[String], opts: Options) { - //println!("spec length={}, args={:?}", spec_text.len(), args); - let (first, last) = if args.is_empty() { - (None, None) - } else { - let mut iter = args[0].split(".."); - let first = iter.next().and_then(|s| s.parse().ok()); - let last = match iter.next() { - Some(s) => s.parse().ok(), - None => first - }; - (first, last) - }; - - let spec = Spec::new(spec_text); - let mut tests_failed = 0; - let mut tests_run = 0; - let mut fail_report = String::new(); - - for test in spec { - if first.map(|fst| test.n < fst).unwrap_or(false) { continue } - if last.map(|lst| test.n > lst).unwrap_or(false) { break } - - if test.n % 10 == 1 { - if test.n % 40 == 1 { - if test.n > 1 { - println!(""); - } - } else { - print!(" "); - } - print!("[{:3}]", test.n); - } else if test.n % 10 == 6 { - print!(" "); - } - - let our_html = render_html(&test.input, opts); - - if our_html == test.expected { - print!("."); - } else { - if tests_failed == 0 { - fail_report = format!("\nFAIL {}:\n\n---input---\n{:?}\n\n---wanted---\n{:?}\n\n---got---\n{:?}\n", - test.n, test.input, test.expected, our_html); - } - print!("X"); - tests_failed += 1; - } - - let _ = io::stdout().flush(); - tests_run += 1; - } - - println!("\n{}/{} tests passed", tests_run - tests_failed, tests_run); - print!("{}", fail_report); -} - -fn brief(program: ProgramName) -> String - where ProgramName: std::fmt::Display { - return format!("Usage: {} FILE [options]", program); -} - -pub fn main() { - let args: Vec<_> = env::args().collect(); - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "this help message"); - opts.optflag("d", "dry-run", "dry run, produce no output"); - opts.optflag("e", "events", "print event sequence instead of rendering"); - opts.optflag("T", "enable-tables", "enable GitHub-style tables"); - opts.optflag("F", "enable-footnotes", "enable Hoedown-style footnotes"); - opts.optopt("s", "spec", "run tests from spec file", "FILE"); - opts.optopt("b", "bench", "run benchmark", "FILE"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - let message = format!("{}\n{}\n", - f.to_string(), - opts.usage(&brief(&args[0]))); - if let Err(err) = write!(std::io::stderr(), "{}", message) { - panic!("Failed to write to standard error: {}\n\ - Error encountered while trying to log the \ - following message: \"{}\"", - err, - message); - } - std::process::exit(1); - } - }; - if matches.opt_present("help") { - println!("{}", opts.usage(&brief(&args[0]))); - return; - } - let mut opts = Options::empty(); - if matches.opt_present("enable-tables") { - opts.insert(OPTION_ENABLE_TABLES); - } - if matches.opt_present("enable-footnotes") { - opts.insert(OPTION_ENABLE_FOOTNOTES); - } - if let Some(filename) = matches.opt_str("spec") { - run_spec(&read_file(&filename).replace("→", "\t"), &matches.free, opts); - } else if let Some(filename) = matches.opt_str("bench") { - let inp = read_file(&filename); - for _ in 0..1000 { - let _ = render_html(&inp, opts); - } - } else { - let mut input = String::new(); - if let Err(why) = io::stdin().read_to_string(&mut input) { - panic!("couldn't read from stdin: {}", why) - } - if matches.opt_present("events") { - print_events(&input, opts); - } else if matches.opt_present("dry-run") { - dry_run(&input, opts); - } else { - print!("{}", render_html(&input, opts)); - } - } -} diff --git a/vendor/pulldown-cmark-0.1.2/src/parse.rs b/vendor/pulldown-cmark-0.1.2/src/parse.rs deleted file mode 100644 index 07e64e2269..0000000000 --- a/vendor/pulldown-cmark-0.1.2/src/parse.rs +++ /dev/null @@ -1,1756 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//! Raw parser, for doing a single pass over input. - -use scanners::*; -use utils; -use std::borrow::Cow; -use std::borrow::Cow::{Borrowed}; -use std::collections::{HashMap, HashSet}; -use std::collections::hash_map::Entry; -use std::cmp; - -#[derive(PartialEq, Debug)] -enum State { - StartBlock, - InContainers, - Inline, - TableHead(usize, usize), // limit, next - TableBody, - TableRow, - CodeLineStart, - Code, - InlineCode, - Literal, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -enum Container { - BlockQuote, - List(usize, u8), - ListItem(usize), - FootnoteDefinition, -} - -pub struct RawParser<'a> { - text: &'a str, - off: usize, - - opts: Options, - active_tab: [u8; 256], - - state: State, - stack: Vec<(Tag<'a>, usize, usize)>, - leading_space: usize, - - containers: Vec, - last_line_was_empty: bool, - - /// In case we have a broken link/image reference, we can call this callback - /// with the reference name (both normalized and not normalized) and use - /// the link/title pair returned instead - broken_link_callback: Option<&'a Fn(&str, &str) -> Option<(String, String)>>, - - // state for code fences - fence_char: u8, - fence_count: usize, - fence_indent: usize, - - // info, used in second pass - loose_lists: HashSet, // offset is at list marker - links: HashMap, Cow<'a, str>)>, -} - -pub struct ParseInfo<'a> { - pub loose_lists: HashSet, - pub links: HashMap, Cow<'a, str>)>, -} - -#[derive(Clone, Debug, PartialEq)] -pub enum Tag<'a> { - // block-level tags - Paragraph, - Rule, - - /// A heading. The field indicates the level of the heading. - Header(i32), - - BlockQuote, - CodeBlock(Cow<'a, str>), - - /// A list. If the list is ordered the field indicates the number of the first item. - List(Option), // TODO: add delim and tight for ast (not needed for html) - Item, - FootnoteDefinition(Cow<'a, str>), - - // tables - Table(Vec), - TableHead, - TableRow, - TableCell, - - // span-level tags - Emphasis, - Strong, - Code, - - /// A link. The first field is the destination URL, the second is a title - Link(Cow<'a, str>, Cow<'a, str>), - - /// An image. The first field is the destination URL, the second is a title - Image(Cow<'a, str>, Cow<'a, str>), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum Event<'a> { - Start(Tag<'a>), - End(Tag<'a>), - Text(Cow<'a, str>), - Html(Cow<'a, str>), - InlineHtml(Cow<'a, str>), - FootnoteReference(Cow<'a, str>), - SoftBreak, - HardBreak, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Alignment { - None, - Left, - Center, - Right, -} - -bitflags! { - pub struct Options: u32 { - const OPTION_FIRST_PASS = 1 << 0; - const OPTION_ENABLE_TABLES = 1 << 1; - const OPTION_ENABLE_FOOTNOTES = 1 << 2; - } -} - -const MAX_LINK_NEST: usize = 10; - -impl<'a> RawParser<'a> { - pub fn new_with_links_and_callback(text: &'a str, opts: Options, - links: HashMap, Cow<'a, str>)>, - callback: Option<&'a Fn(&str, &str) -> Option<(String, String)>>) - -> RawParser<'a> { - let mut ret = RawParser { - text: text, - off: if text.starts_with("\u{FEFF}") { 3 } else { 0 }, - opts: opts, - active_tab: [0; 256], - state: State::StartBlock, - leading_space: 0, - stack: Vec::new(), - containers: Vec::new(), - last_line_was_empty: false, - - fence_char: 0, - fence_count: 0, - fence_indent: 0, - - broken_link_callback: callback, - - // info, used in second pass - loose_lists: HashSet::new(), - links: links, - }; - ret.init_active(); - ret.skip_blank_lines(); - ret - } - - pub fn new_with_links(text: &'a str, opts: Options, - links: HashMap, Cow<'a, str>)>) -> RawParser<'a> { - Self::new_with_links_and_callback(text, opts, links, None) - } - - pub fn new(text: &'a str, opts: Options) -> RawParser<'a> { - Self::new_with_links(text, opts, HashMap::new()) - } - - // offset into text representing current parse position, hopefully - // useful for building source maps - pub fn get_offset(&self) -> usize { - self.off - } - - // extract info from parser on finish - pub fn get_info(self) -> ParseInfo<'a> { - ParseInfo { - loose_lists: self.loose_lists, - links: self.links, - } - } - - fn init_active(&mut self) { - if self.opts.contains(OPTION_FIRST_PASS) { - self.active_tab[b'\n' as usize] = 1 - } else { - for &c in b"\x00\t\n\r_\\&*[!`<" { - self.active_tab[c as usize] = 1; - } - } - } - - fn limit(&self) -> usize { - match self.stack.last() { - Some(&(_, limit, _)) => limit, - None => self.text.len() - } - } - - // if end is not known, limit should be text.len(), next should be 0 - fn start(&mut self, tag: Tag<'a>, limit: usize, next: usize) -> Event<'a> { - self.stack.push((tag.clone(), limit, next)); - Event::Start(tag) - } - - fn end(&mut self) -> Event<'a> { - let (tag, _, next) = self.stack.pop().unwrap(); - match tag { - // containers - Tag::BlockQuote | Tag::List(_) | Tag::Item | Tag::FootnoteDefinition(_) => { - let _ = self.containers.pop(); - } - - // block level tags - Tag::Paragraph | Tag::Header(_) | Tag::Rule | Tag::CodeBlock(_) | Tag::Table(_) => { - self.state = State::StartBlock; - // TODO: skip blank lines (for cleaner source maps) - } - - // tables - Tag::TableCell => self.state = State::TableRow, - Tag::TableRow | Tag::TableHead => self.state = State::TableBody, - - // inline - Tag::Code => self.state = State::Inline, - _ => (), - } - if next != 0 { self.off = next; } - - /* - if self.stack.is_empty() { - // TODO maybe: make block ends do this - self.state = State::StartBlock; - self.skip_blank_lines(); - } - */ - Event::End(tag) - } - - fn skip_leading_whitespace(&mut self) { - self.off += scan_whitespace_no_nl(&self.text[self.off .. self.limit()]); - } - - // TODO: this function doesn't respect containers - fn skip_blank_lines(&mut self) { - loop { - let ret = scan_blank_line(&self.text[self.off..]); - if ret == 0 { - break; - } - self.off += ret; - } - } - - // Scan markers and indentation for current container stack - // Return: bytes scanned, whether containers are complete, and remaining space - fn scan_containers(&self, text: &str) -> (usize, bool, usize) { - let (mut i, mut space) = scan_leading_space(text, 0); - for container in &self.containers { - match *container { - Container::BlockQuote => { - if space <= 3 { - let n = scan_blockquote_start(&text[i..]); - if n > 0 { - let (n_sp, next_space) = scan_leading_space(text, i + n); - i += n + n_sp; - space = next_space; - } else { - return (i, false, space); - } - } else { - return (i, false, space); - } - } - Container::FootnoteDefinition | - Container::List(_, _) => (), - Container::ListItem(indent) => { - if space >= indent { - space -= indent; - } else if scan_eol(&text[i..]).1 { - space = 0; - } else { - return (i, false, 0); - } - } - } - } - (i, true, space) - } - - // scans empty lines with current container stack - // returns number of bytes scanned, number of empty lines - // note: EOF counts as a line ending for counting lines - fn scan_empty_lines(&self, text: &str) -> (usize, usize) { - let mut i = 0; - let mut lines = 0; - loop { - let (n, scanned, _) = self.scan_containers(&text[i..]); - if !scanned { - return (i, lines); - } - if i == text.len() { - return (i, lines + 1); - } - let n_blank = scan_eol(&text[i + n ..]).0; - if n_blank == 0 { - return (i, lines); - } - i += n + n_blank; - lines += 1; - } - } - - // scans whitespace, skipping past containers on newline - fn scan_whitespace_inline(&self, text: &str) -> usize { - let i = scan_whitespace_no_nl(text); - if let (n, true) = scan_eol(&text[i..]) { - let (n_containers, _, space) = self.scan_containers(&text[i + n ..]); - let j = i + n + n_containers; - if !self.is_inline_block_end(&text[j..], space) { - return j; - } - } - i - } - - fn at_list(&self, level: usize) -> Option { - let len = self.containers.len(); - if len >= level { - if let Container::List(offset, _) = self.containers[len - level] { - return Some(offset); - } - } - None - } - - fn start_block(&mut self) -> Option> { - let size = self.text.len(); - //println!("start_block {}", self.off); - while self.off < size { - //println!("start_block loop {} {}", self.off, self.last_line_was_empty); - if self.off >= self.limit() { - return Some(self.end()); - } - if self.state != State::InContainers { - let (n, scanned, space) = self.scan_containers(&self.text[self.off ..]); - if !scanned { - return Some(self.end()); - } - self.leading_space = space; - self.off += n; - self.state = State::InContainers; - } - - let (n, at_eol) = scan_eol(&self.text[self.off ..]); - if at_eol { - self.off += n; - self.state = State::StartBlock; - // two empty lines closes lists, one empty line closes a footnote - let (n, empty_lines) = self.scan_empty_lines(&self.text[self.off ..]); - for i in (0..self.stack.len()).rev() { - let is_break = match self.stack[i].0 { - Tag::List(_) => empty_lines >= 1, - Tag::Item => false, - Tag::FootnoteDefinition(_) => true, - _ => break, - }; - if is_break { - for tag in &mut self.stack[i..] { - tag.1 = self.off; // limit - tag.2 = self.off; // next - } - self.stack[i].2 = self.off + n; // next - return Some(self.end()); - } - } - self.off += n; - if let Some(_) = self.at_list(2) { - self.last_line_was_empty = true; - } - continue; - } - - //println!("checking loose {} {:?}", self.last_line_was_empty, self.at_list(2)); - if self.last_line_was_empty { - if let Some(offset) = self.at_list(2) { - // list item contains two blocks separated by empty line - self.loose_lists.insert(offset); - } - } - - if self.leading_space >= 4 && !self.at_list(1).is_some() { - // see below - if let Some(&Container::List(_, _)) = self.containers.last() { - return Some(self.end()); - } - return Some(self.start_indented_code()); - } - - let tail = &self.text[self.off ..]; - - // must be before list item because ambiguous - let n = scan_hrule(tail); - if n != 0 { - self.last_line_was_empty = false; - // see below - if let Some(&Container::List(_, _)) = self.containers.last() { - return Some(self.end()); - } - self.off += n; - return Some(self.start_hrule()); - } - - let (n, c, start, indent) = scan_listitem(tail); - if n != 0 { - if self.last_line_was_empty { - if let Some(offset) = self.at_list(1) { - // two list items separated by empty line - self.loose_lists.insert(offset); - } - } - self.last_line_was_empty = false; - return Some(self.start_listitem(n, c, start, indent)); - } - - // not a list item, so if we're in a list, close it - if let Some(&Container::List(_, _)) = self.containers.last() { - return Some(self.end()); - } - self.last_line_was_empty = false; - - let c = tail.as_bytes()[0]; - match c { - b'#' => { - let (n, level) = scan_atx_header(tail); - if n != 0 { - self.off += n; - return Some(self.start_atx_header(level)); - } - } - b'`' | b'~' => { - let (n, ch) = scan_code_fence(tail); - if n != 0 { - return Some(self.start_code_fence(n, ch, n)); - } - } - b'>' => { - let n = scan_blockquote_start(tail); - if n != 0 { - self.off += n; - let (n, space) = scan_leading_space(self.text, self.off); - self.off += n; - self.leading_space = space; - self.containers.push(Container::BlockQuote); - return Some(self.start(Tag::BlockQuote, self.text.len(), 0)); - } - } - b'<' => { - if self.is_html_block(tail) { - return Some(self.do_html_block()); - } - } - b'[' => { - if self.opts.contains(OPTION_ENABLE_FOOTNOTES) { - if let Some((name, n)) = self.parse_footnote_definition(tail) { - if self.containers.last() == Some(&Container::FootnoteDefinition) { - return Some(self.end()); - } - self.off += n; - self.containers.push(Container::FootnoteDefinition); - return Some(self.start(Tag::FootnoteDefinition(Cow::Borrowed(name)), self.text.len(), 0)); - } - } - if self.try_link_reference_definition(tail) { - continue; - } - } - _ => () - } - return Some(self.start_paragraph()); - } - None - } - - // can start a paragraph, a setext header, or a table, as they start similarly - fn start_paragraph(&mut self) -> Event<'a> { - let mut i = self.off + scan_nextline(&self.text[self.off..]); - - if let (n, true, space) = self.scan_containers(&self.text[i..]) { - i += n; - if space <= 3 { - let (n, level) = scan_setext_header(&self.text[i..]); - if n != 0 { - let next = i + n; - while i > self.off && is_ascii_whitespace(self.text.as_bytes()[i - 1]) { - i -= 1; - } - self.state = State::Inline; - return self.start(Tag::Header(level), i, next); - } - if self.opts.contains(OPTION_ENABLE_TABLES) { - let (n, cols) = scan_table_head(&self.text[i..]); - if n != 0 { - let next = i + n; - while i > self.off && is_ascii_whitespace(self.text.as_bytes()[i - 1]) { - i -= 1; - } - self.state = State::TableHead(i, next); - return self.start(Tag::Table(cols), self.text.len(), 0); - } - } - } - } - - let size = self.text.len(); - self.state = State::Inline; - self.start(Tag::Paragraph, size, 0) - } - - fn start_table_head(&mut self) -> Event<'a> { - assert!(self.opts.contains(OPTION_ENABLE_TABLES)); - if let State::TableHead(limit, next) = self.state { - self.state = State::TableRow; - return self.start(Tag::TableHead, limit, next); - } else { - panic!(); - } - } - - fn start_table_body(&mut self) -> Event<'a> { - assert!(self.opts.contains(OPTION_ENABLE_TABLES)); - let (off, _) = match self.scan_containers(&self.text[self.off ..]) { - (n, true, space) => (self.off + n, space), - _ => { - return self.end(); - } - }; - let n = scan_blank_line(&self.text[off..]); - if n != 0 { - self.off = off + n; - return self.end(); - } - self.state = State::TableRow; - self.off = off; - self.start(Tag::TableRow, self.text.len(), 0) - } - - fn start_hrule(&mut self) -> Event<'a> { - let limit = self.off; // body of hrule is empty - self.state = State::Inline; // handy state for producing correct end tag - self.start(Tag::Rule, limit, limit) - } - - fn start_atx_header(&mut self, level: i32) -> Event<'a> { - self.skip_leading_whitespace(); - let tail = &self.text[self.off..]; - let next = scan_nextline(tail); - let mut limit = next; - while limit > 0 && is_ascii_whitespace(tail.as_bytes()[limit - 1]) { - limit -= 1; - } - let mut end = limit; - while end > 0 && tail.as_bytes()[end - 1] == b'#' { - end -= 1; - } - if end == 0 { - limit = end; - } else if is_ascii_whitespace(tail.as_bytes()[end - 1]) { - limit = end - 1; - } - while limit > 0 && is_ascii_whitespace(tail.as_bytes()[limit - 1]) { - limit -= 1; - } - let limit = limit + self.off; - let next = next + self.off; - self.state = State::Inline; - self.start(Tag::Header(level), limit, next) - } - - fn start_indented_code(&mut self) -> Event<'a> { - self.fence_char = b'\0'; - self.fence_indent = 4; - let size = self.text.len(); - self.state = State::Code; - self.start(Tag::CodeBlock(Borrowed("")), size, 0) - } - - fn start_listitem(&mut self, n: usize, c: u8, start: usize, indent: usize) -> Event<'a> { - let indent = self.leading_space + indent; - match self.containers.last() { - Some(&Container::List(_, c2)) => { - if c != c2 { - // mismatched list type or delimeter - return self.end(); - } - self.off += n; - let n_blank = scan_blank_line(&self.text[self.off ..]); - if n_blank != 0 { - self.off += n_blank; - self.state = State::StartBlock; - } else { - // TODO: deal with tab - let (n, space) = scan_leading_space(self.text, self.off); - self.off += n; - self.leading_space = space; - } - self.containers.push(Container::ListItem(indent)); - self.start(Tag::Item, self.text.len(), 0) - } - _ => { - self.containers.push(Container::List(self.off, c)); - // arguably this should be done in the scanner, it should return option - let startopt = if c == b'.' || c == b')' { Some(start) } else { None }; - self.start(Tag::List(startopt), self.text.len(), 0) - } - } - } - - fn start_code_fence(&mut self, n: usize, ch: u8, count: usize) -> Event<'a> { - self.fence_char = ch; - self.fence_count = count; - self.fence_indent = self.leading_space; - let beg_info = self.off + n; - let next_line = beg_info + scan_nextline(&self.text[beg_info..]); - self.off = next_line; - let info = unescape(self.text[beg_info..next_line].trim()); - let size = self.text.len(); - self.state = State::CodeLineStart; - self.start(Tag::CodeBlock(info), size, 0) - } - - fn next_code_line_start(&mut self) -> Event<'a> { - let (off, space) = match self.scan_containers(&self.text[self.off ..]) { - (n, true, space) => (self.off + n, space), - _ => { - return self.end(); - } - }; - - if self.fence_char == b'\0' { - let n = scan_blank_line(&self.text[off..]); - if n != 0 { - // TODO performance: this scanning is O(n^2) in the number of empty lines - let (n_empty, _lines) = self.scan_empty_lines(&self.text[off + n ..]); - let next = off + n + n_empty; - let (n_containers, scanned, nspace) = self.scan_containers(&self.text[next..]); - // TODO; handle space - if !scanned || self.is_code_block_end(next + n_containers, nspace) { - //println!("was end: {}", next + n_containers); - return self.end(); - } else { - self.off = off; - //println!("code line start space={}, off={}", space, off); - self.leading_space = space; - return self.next_code(); - } - } - } - - if self.is_code_block_end(off, space) { - let ret = self.end(); - if self.fence_char != b'\0' { - self.off = off + scan_nextline(&self.text[off..]); - } - ret - } else { - self.off = off; - self.state = State::Code; - self.leading_space = space; - self.next_code() - } - } - - fn next_code(&mut self) -> Event<'a> { - if self.leading_space > self.fence_indent { - // TODO: might try to combine spaces in text, for fewer events - let space = self.leading_space; - self.leading_space = 0; - return Event::Text(spaces(space - self.fence_indent)); - } - let bytes = self.text.as_bytes(); - let mut beg = self.off; - let mut i = beg; - loop { - match bytes[i..].iter().position(|&c| c < b' ') { - Some(j) => i += j, - None => { - i += bytes[i..].len(); - break; - } - } - match bytes[i] { - b'\n' => { - i += 1; - self.state = State::CodeLineStart; - break; - } - b'\r' => { - // just skip it (does not support '\r' only line break) - if i > beg { break; } - beg += 1; - } - _ => () - } - i += 1; - } - self.off = i; - Event::Text(Borrowed(&self.text[beg..i])) - } - - fn is_code_block_end(&self, loc: usize, space: usize) -> bool { - let tail = &self.text[loc..]; - if self.fence_char == b'\0' { - // indented code block - space < 4 - } else if space <= 3 { - let (n, c) = scan_code_fence(tail); - c == self.fence_char && n >= self.fence_count && - (n >= tail.len() || scan_blank_line(&tail[n..]) != 0) - } else { - false - } - } - - // # HTML blocks - - fn scan_html_block_tag(&self, data: &'a str) -> (usize, &'a str) { - let mut i = scan_ch(data, b'<'); - if i == 0 { return (0, "") } - i += scan_ch(&data[i..], b'/'); - let n = scan_while(&data[i..], is_ascii_alphanumeric); - // TODO: scan attributes and > - (i + n, &data[i .. i + n]) - } - - fn is_html_block(&self, data: &str) -> bool { - let (n_tag, tag) = self.scan_html_block_tag(data); - (n_tag > 0 && is_html_tag(tag)) || - data.starts_with(" Option<&'static str> { - static BEGIN_TAGS: &'static [&'static str; 3] = &["script", "pre", "style"]; - static END_TAGS: &'static [&'static str; 3] = &["", "", ""]; - - for (beg_tag, end_tag) in BEGIN_TAGS.iter().zip(END_TAGS.iter()) { - if self.off + 1 + beg_tag.len() < self.text.len() && - self.text[self.off + 1..].starts_with(&beg_tag[..]) { - let pos = self.off + beg_tag.len() + 1; - let s = self.text.as_bytes()[pos]; - if s == b' ' || s == b'\n' || s == b'>' { - return Some(end_tag); - } - } - } - static ST_BEGIN_TAGS: &'static [&'static str; 3] = &["", "?>", "]]>"]; - for (beg_tag, end_tag) in ST_BEGIN_TAGS.iter().zip(ST_END_TAGS.iter()) { - if self.off + 1 + beg_tag.len() < self.text.len() && - self.text[self.off + 1..].starts_with(&beg_tag[..]) { - return Some(end_tag); - } - } - if self.off + 4 < self.text.len() && - self.text[self.off + 1..].starts_with("= 'A' && c <= 'Z' { - return Some(">"); - } - } - None - } - - fn do_html_block(&mut self) -> Event<'a> { - let mut i = self.off; - if let Some(tag) = self.get_html_tag() { - let text = self.text[i..].split(tag).take(1).next().unwrap_or(""); - self.off = i + text.len(); - self.state = State::StartBlock; - return Event::Html(utils::cow_append(Borrowed(""), Borrowed(&self.text[i..self.off]))); - } - let size = self.text.len(); - let mut out = Borrowed(""); - let mut mark = i; - loop { - let n = scan_nextline(&self.text[i..]); - i += n; - if n >= 2 && self.text.as_bytes()[i - 2] == b'\r' { - if self.leading_space > 0 { - out = utils::cow_append(out, spaces(self.leading_space)); - self.leading_space = 0; - } - out = utils::cow_append(out, Borrowed(&self.text[mark .. i - 2])); - mark = i - 1; - } - let (n, scanned, space) = self.scan_containers(&self.text[i..]); - let n_blank = scan_blank_line(&self.text[i + n ..]); - if n != 0 || !scanned || i + n == size || n_blank != 0 { - if self.leading_space > 0 { - out = utils::cow_append(out, spaces(self.leading_space)); - } - self.leading_space = space; - out = utils::cow_append(out, Borrowed(&self.text[mark..i])); - mark = i + n; - } - if !scanned || i + n == size || n_blank != 0 { - self.off = i; // TODO: skip blank lines (cleaner source maps) - self.state = State::StartBlock; - return Event::Html(out) - } - } - } - - // # Link reference definitions - - fn try_link_reference_definition(&mut self, data: &'a str) -> bool { - let (n_link, text_beg, text_end, max_nest) = self.scan_link_label(data); - if n_link == 0 || max_nest > 1 { return false; } - let n_colon = scan_ch(&data[n_link ..], b':'); - if n_colon == 0 { return false; } - let mut i = n_link + n_colon; - i += self.scan_whitespace_inline(&data[i..]); - let linkdest = scan_link_dest(&data[i..]); - if linkdest.is_none() { return false; } - let (n_dest, raw_dest) = linkdest.unwrap(); - if n_dest == 0 { return false; } - i += n_dest; - i += scan_whitespace_no_nl(&data[i..]); - let n_nl = self.scan_whitespace_inline(&data[i..]); - let (n_title, title_beg, title_end) = self.scan_link_title(&data[i + n_nl ..]); - let title = if n_title == 0 { - Borrowed("") - } else { - let (title_beg, title_end) = (i + n_nl + title_beg, i + n_nl + title_end); - i += n_nl + n_title; - unescape(&data[title_beg..title_end]) - }; - i += scan_whitespace_no_nl(&data[i..]); - if let (n_eol, true) = scan_eol(&data[i..]) { - i += n_eol; - } else { - return false; - } - - let linktext = self.normalize_link_ref(&data[text_beg..text_end]); - if linktext.is_empty() { - return false; - } - if let Entry::Vacant(entry) = self.links.entry(linktext) { - let dest = unescape(raw_dest); - entry.insert((dest, title)); - } - self.state = State::StartBlock; - self.off += i; - true - } - - // normalize whitespace and case-fold - fn normalize_link_ref(&self, raw: &str) -> String { - let mut need_space = false; - let mut result = String::new(); - let mut i = 0; - while i < raw.len() { - let n = scan_nextline(&raw[i..]); - for c in raw[i.. i + n].chars() { - if c.is_whitespace() { - need_space = true; - } else { - if need_space && !result.is_empty() { - result.push(' '); - } - // TODO: Unicode case folding can differ from lowercase (ß) - result.extend(c.to_lowercase()); - need_space = false; - } - } - i += n; - if i == raw.len() { break; } - i += self.scan_containers(&raw[i..]).0; - need_space = true; - } - result - } - - // determine whether the line starting at loc ends the block - fn is_inline_block_end(&self, data: &str, space: usize) -> bool { - data.is_empty() || - scan_blank_line(data) != 0 || - space <= 3 && (scan_hrule(data) != 0 || - scan_atx_header(data).0 != 0 || - scan_code_fence(data).0 != 0 || - scan_blockquote_start(data) != 0 || - scan_listitem(data).0 != 0 || - self.is_html_block(data)) - } - - fn next_table_cell(&mut self) -> Event<'a> { - assert!(self.opts.contains(OPTION_ENABLE_TABLES)); - let bytes = self.text.as_bytes(); - let mut beg = self.off + scan_whitespace_no_nl(&self.text[self.off ..]); - let mut i = beg; - let limit = self.limit(); - if i < limit && bytes[i] == b'|' { - i += 1; - beg += 1; - self.off += 1; - } - if i >= limit { - self.off = limit; - return self.end(); - } - let mut n = 0; - while i < limit { - let c = bytes[i]; - if c == b'\\' && i + 1 < limit && bytes[i + 1] == b'|' { - i += 2; - continue; - } else if c == b'|' { - n = 0; - break; - } - n = if is_ascii_whitespace(bytes[i]) { scan_blank_line(&self.text[i..]) } else { 0 }; - if n != 0 { - if i > beg { - n = 0; - } - break; - } - i += 1; - } - if i > beg { - self.state = State::Inline; - self.start(Tag::TableCell, i, i + n) - } else { - self.off = i + n; - self.end() - } - } - - fn next_inline(&mut self) -> Event<'a> { - let bytes = self.text.as_bytes(); - let beg = self.off; - let mut i = beg; - let limit = self.limit(); - while i < limit { - match bytes[i..limit].iter().position(|&c| self.active_tab[c as usize] != 0) { - Some(pos) => i += pos, - None => { i = limit; break; } - } - let c = bytes[i]; - if c == b'\n' || c == b'\r' { - let n = scan_trailing_whitespace(&self.text[beg..i]); - let end = i - n; - if end > beg { - self.off = end; - return Event::Text(Borrowed(&self.text[beg..end])); - } - if c == b'\r' && i + 1 < limit && self.text.as_bytes()[i + 1] == b'\n' { - i += 1; - } - i += 1; - let next = i; - let (n_containers, _, space) = self.scan_containers(&self.text[i..limit]); - i += n_containers; - if self.is_inline_block_end(&self.text[i..limit], space) { - self.off = next; - return self.end(); - } - i += scan_whitespace_no_nl(&self.text[i..limit]); - self.off = i; - return if n >= 2 { Event::HardBreak } else { Event::SoftBreak }; - } - self.off = i; - if i > beg { - return Event::Text(Borrowed(&self.text[beg..i])); - } - if let Some(event) = self.active_char(c) { - return event; - } - i = self.off; // let handler advance offset even on None - i += 1; - } - if i > beg { - self.off = i; - Event::Text(Borrowed(&self.text[beg..i])) - } else { - self.end() - } - } - - fn active_char(&mut self, c: u8) -> Option> { - match c { - b'\x00' => Some(self.char_null()), - b'\t' => Some(self.char_tab()), - b'\\' => self.char_backslash(), - b'&' => self.char_entity(), - b'_' | - b'*' => self.char_emphasis(), - b'[' if self.opts.contains(OPTION_ENABLE_FOOTNOTES) => self.char_link_footnote(), - b'[' | b'!' => self.char_link(), - b'`' => self.char_backtick(), - b'<' => self.char_lt(), - _ => None - } - } - - fn char_null(&mut self) -> Event<'a> { - self.off += 1; - Event::Text(Borrowed("\u{fffd}")) - } - - // expand tab in content (used for code and inline) - // scan backward to find offset, counting unicode code points - fn char_tab(&mut self) -> Event<'a> { - let count = count_tab(&self.text.as_bytes()[.. self.off]); - self.off += 1; - Event::Text(Borrowed(&" "[..count])) - } - - fn char_backslash(&mut self) -> Option> { - let limit = self.limit(); - if self.off + 1 < limit { - if let (_, true) = scan_eol(&self.text[self.off + 1 .. limit]) { - let n_white = self.scan_whitespace_inline(&self.text[self.off + 1 .. limit]); - let space = 0; // TODO: figure this out - if !self.is_inline_block_end(&self.text[self.off + 1 + n_white .. limit], space) { - self.off += 1 + n_white; - return Some(Event::HardBreak); - } - } - let c = self.text.as_bytes()[self.off + 1]; - if is_ascii_punctuation(c) { - self.off += 2; - return Some(Event::Text(Borrowed(&self.text[self.off - 1 .. self.off]))); - } - } - None - } - - fn char_entity(&mut self) -> Option> { - match scan_entity(&self.text[self.off ..]) { - (n, Some(value)) => { - self.off += n; - Some(Event::Text(value)) - } - _ => None - } - } - - fn char_emphasis(&mut self) -> Option> { - // can see to left for flanking info, but not past limit - let limit = self.limit(); - let data = &self.text[..limit]; - - let c = data.as_bytes()[self.off]; - let (n, can_open, _can_close) = compute_open_close(data, self.off, c); - if !can_open { - return None; - } - let mut stack = vec![n]; // TODO performance: don't allocate - let mut i = self.off + n; - while i < limit { - let c2 = data.as_bytes()[i]; - if c2 == b'\n' && !is_escaped(data, i) { - let (_, complete, space) = self.scan_containers(&self.text[i..]); - if !complete { - i += 1; - continue; - } - if self.is_inline_block_end(&self.text[i + 1 .. limit], space) { - return None - } else { - i += 1; - } - } else if c2 == c && !is_escaped(data, i) { - let (mut n2, can_open, can_close) = compute_open_close(data, i, c); - if can_close { - loop { - let ntos = stack.pop().unwrap(); - if ntos > n2 { - stack.push(ntos - n2); - break; - } - if stack.is_empty() { - let npop = if ntos < n2 { ntos } else { n2 }; - if npop == 1 { - self.off += 1; - return Some(self.start(Tag::Emphasis, i, i + 1)); - } else { - self.off += 2; - let next = i + npop; - return Some(self.start(Tag::Strong, next - 2, next)); - } - } else { - i += ntos; - n2 -= ntos; - } - } - } else if can_open { - stack.push(n2); - } - i += n2; - } else if c2 == b'`' { - let (n, beg, _) = self.scan_inline_code(&self.text[i..limit]); - if n != 0 { - i += n; - } else { - i += beg; - } - } else if c2 == b'<' { - let n = self.scan_autolink_or_html(&self.text[i..limit]); - if n != 0 { - i += n; - } else { - i += 1; - } - } else if c2 == b'[' { - if self.opts.contains(OPTION_ENABLE_FOOTNOTES) { - if let Some((_, n)) = self.parse_footnote(&self.text[i..limit]) { - i += n; - continue; - } - } - if let Some((_, _, _, n)) = self.parse_link(&self.text[i..limit], false) { - i += n; - } else { - i += 1; - } - } else { - i += 1; - } - } - None - } - - // # Links - - // scans a link label, example [link] - // return value is: total bytes, start of text, end of text, max nesting - fn scan_link_label(&self, data: &str) -> (usize, usize, usize, usize) { - let mut i = scan_ch(data, b'['); - if i == 0 { return (0, 0, 0, 0); } - let text_beg = i; - let mut max_nest = 1; - let mut nest = 1; - loop { - if i >= data.len() { return (0, 0, 0, 0); } - match data.as_bytes()[i] { - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return (0, 0, 0, 0); } - i += n; - } - b'[' => { - nest += 1; - if nest == MAX_LINK_NEST { return (0, 0, 0, 0); } - max_nest = cmp::max(max_nest, nest); - i += 1; - } - b']' => { - nest -= 1; - if nest == 0 { - break; - } - i += 1; - } - b'\\' => i += 1, - b'<' => { - let n = self.scan_autolink_or_html(&data[i..]); - if n != 0 { - i += n; - } else { - i += 1; - } - } - b'`' => { - let (n, beg, _) = self.scan_inline_code(&data[i..]); - if n != 0 { - i += n; - } else { - i += beg; - } - } - _ => i += 1 - } - } - let text_end = i; - i += 1; // skip closing ] - (i, text_beg, text_end, max_nest) - } - - fn scan_link_title(&self, data: &str) -> (usize, usize, usize) { - let size = data.len(); - if size == 0 { return (0, 0, 0); } - let mut i = 0; - let titleclose = match data.as_bytes()[i] { - b'(' => b')', - b'\'' => b'\'', - b'\"' => b'\"', - _ => return (0, 0, 0) - }; - i += 1; - let title_beg = i; - while i < size { - match data.as_bytes()[i] { - x if x == titleclose => break, - b'\\' => i += 2, // may be > size - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return (0, 0, 0); } - i += n; - } - _ => i += 1 - } - } - if i >= size { return (0, 0, 0); } - let title_end = i; - i += 1; - (i, title_beg, title_end) - } - - fn char_link(&mut self) -> Option> { - self.parse_link(&self.text[self.off .. self.limit()], false).map(|(tag, beg, end, n)| { - let off = self.off; - self.off += beg; - self.start(tag, off + end, off + n) - }) - } - - // return: tag, begin, end, total size - fn parse_link(&self, data: &'a str, recur: bool) -> Option<(Tag<'a>, usize, usize, usize)> { - let size = data.len(); - - // scan link text - let i = scan_ch(data, b'!'); - let is_image = i == 1; - let (n, text_beg, text_end, max_nest) = self.scan_link_label(&data[i..]); - if n == 0 { return None; } - let (text_beg, text_end) = (text_beg + i, text_end + i); - if !is_image && !recur && max_nest > 1 && self.contains_link(&data[text_beg..text_end]) { - // disallow nested links in links (but ok in images) - return None; - } - let mut i = i + n; - - // scan dest - let (dest, title, beg, end, next) = if data[i..].starts_with('(') { - i += 1; - i += self.scan_whitespace_inline(&data[i..]); - if i >= size { return None; } - - let linkdest = scan_link_dest(&data[i..]); - if linkdest.is_none() { return None; } - let (n, raw_dest) = linkdest.unwrap(); - let dest = unescape(raw_dest); - i += n; - - i += self.scan_whitespace_inline(&data[i..]); - if i == size { return None; } - - // scan title - let (n_title, title_beg, title_end) = self.scan_link_title(&data[i..]); - let title = if n_title == 0 { - Borrowed("") - } else { - let (title_beg, title_end) = (i + title_beg, i + title_end); - i += n_title; - // TODO: not just unescape, remove containers from newlines - unescape(&data[title_beg..title_end]) - }; - i += self.scan_whitespace_inline(&data[i..]); - if i == size || data.as_bytes()[i] != b')' { return None; } - i += 1; - (dest, title, text_beg, text_end, i) - } else { - // try link reference - let j = i + self.scan_whitespace_inline(&data[i..]); - let (n_ref, ref_beg, ref_end, _) = self.scan_link_label(&data[j..]); - let (ref_beg, ref_end) = if n_ref == 0 || ref_beg == ref_end { - (text_beg, text_end) - } else { - (j + ref_beg, j + ref_end) - }; - if n_ref != 0 { - i = j + n_ref; - } - let reference = self.normalize_link_ref(&data[ref_beg..ref_end]); - let (dest, title) = match self.links.get(&reference) { - Some(&(ref dest, ref title)) => (dest.clone(), title.clone()), - None => { - if let Some(ref callback) = self.broken_link_callback { - if let Some(val) = callback(&reference, &data[ref_beg..ref_end]) { - (val.0.into(), val.1.into()) - } else { - return None; - } - } else { - return None; - } - } - }; - (dest, title, text_beg, text_end, i) - }; - if is_image { - Some((Tag::Image(dest, title), beg, end, next)) - } else { - Some((Tag::Link(dest, title), beg, end, next)) - } - } - - // determine whether there's a link anywhere in the text - // TODO: code duplication with scan_link_label is unpleasant - fn contains_link(&self, data: &str) -> bool { - let mut i = 0; - while i < data.len() { - match data.as_bytes()[i] { - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return false; } - i += n; - continue; - } - b'!' => { - if scan_ch(&data[i + 1 ..], b'[') != 0 { - // ok to contain image, skip over opening bracket - i += 1; - } - } - b'[' => { - if self.opts.contains(OPTION_ENABLE_FOOTNOTES) && self.parse_footnote(&data[i..]).is_some() { - return false; - } - if self.parse_link(&data[i..], true).is_some() { return true; } - } - b'\\' => i += 1, - b'<' => { - let n = self.scan_autolink_or_html(&data[i..]); - if n != 0 { - i += n; - } else { - i += 1; - } - } - b'`' => { - let (n, beg, _) = self.scan_inline_code(&data[i..]); - if n != 0 { - i += n; - } else { - i += beg; - } - } - _ => () - } - i += 1; - } - false - } - - // # Footnotes - - fn parse_footnote_definition<'b>(&self, data: &'b str) -> Option<(&'b str, usize)> { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - self.parse_footnote(data).and_then(|(name, len)| { - let n_colon = scan_ch(&data[len ..], b':'); - if n_colon == 0 { - None - } else { - let space = scan_whitespace_no_nl(&data[len + n_colon..]); - // skip newline if definition is on a line by itself, as likely that - // means the footnote definition is a complex block. - let mut i = len + n_colon + space; - if let (n, true) = scan_eol(&data[i..]) { - let (n_containers, _, _) = self.scan_containers(&data[i + n ..]); - i += n + n_containers; - } - Some((name, i)) - } - }) - } - - fn char_link_footnote(&mut self) -> Option> { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - if let Some((name, end)) = self.parse_footnote(&self.text[self.off .. self.limit()]) { - self.off += end; - Some(Event::FootnoteReference(Cow::Borrowed(name))) - } else { - self.char_link() - } - } - - fn parse_footnote<'b>(&self, data: &'b str) -> Option<(&'b str, usize)> { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - let (n_footnote, text_beg, text_end) = self.scan_footnote_label(data); - if n_footnote == 0 { return None; } - Some((&data[text_beg..text_end], n_footnote)) - } - - fn scan_footnote_label(&self, data: &str) -> (usize, usize, usize) { - assert!(self.opts.contains(OPTION_ENABLE_FOOTNOTES)); - let mut i = scan_ch(data, b'['); - if i == 0 { return (0, 0, 0); } - if i >= data.len() || data.as_bytes()[i] != b'^' { return (0, 0, 0); } - i += 1; - let text_beg = i; - loop { - if i >= data.len() { return (0, 0, 0); } - match data.as_bytes()[i] { - b'\n' => { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return (0, 0, 0); } - i += n; - continue; - } - b']' => break, - b'\\' => i += 1, - _ => () - } - i += 1; - } - let text_end = i; - i += 1; // skip closing ] - (i, text_beg, text_end) - } - - // # Autolinks and inline HTML - - fn char_lt(&mut self) -> Option> { - let tail = &self.text[self.off .. self.limit()]; - if let Some((n, link)) = scan_autolink(tail) { - let next = self.off + n; - self.off += 1; - self.state = State::Literal; - return Some(self.start(Tag::Link(link, Borrowed("")), next - 1, next)) - } - let n = self.scan_inline_html(tail); - if n != 0 { - return Some(self.inline_html_event(n)) - } - None - } - - fn scan_autolink_or_html(&self, data: &str) -> usize { - if let Some((n, _)) = scan_autolink(data) { - n - } else { - self.scan_inline_html(data) - } - } - - fn scan_inline_html(&self, data: &str) -> usize { - let n = self.scan_html_tag(data); - if n != 0 { return n; } - let n = self.scan_html_comment(data); - if n != 0 { return n; } - let n = self.scan_processing_instruction(data); - if n != 0 { return n; } - let n = self.scan_declaration(data); - if n != 0 { return n; } - let n = self.scan_cdata(data); - if n != 0 { return n; } - 0 - } - - fn scan_html_tag(&self, data: &str) -> usize { - let size = data.len(); - let mut i = 0; - if scan_ch(data, b'<') == 0 { return 0; } - i += 1; - let n_slash = scan_ch(&data[i..], b'/'); - i += n_slash; - if i == size || !is_ascii_alpha(data.as_bytes()[i]) { return 0; } - i += 1; - i += scan_while(&data[i..], is_ascii_alphanumeric); - if n_slash == 0 { - loop { - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { break; } - i += n; - let n = scan_attribute_name(&data[i..]); - if n == 0 { break; } - i += n; - let n = self.scan_whitespace_inline(&data[i..]); - if scan_ch(&data[i + n ..], b'=') != 0 { - i += n + 1; - i += self.scan_whitespace_inline(&data[i..]); - let n_attr = self.scan_attribute_value(&data[i..]); - if n_attr == 0 { return 0; } - i += n_attr; - } - } - i += self.scan_whitespace_inline(&data[i..]); - i += scan_ch(&data[i..], b'/'); - } else { - i += self.scan_whitespace_inline(&data[i..]); - } - if scan_ch(&data[i..], b'>') == 0 { return 0; } - i += 1; - i - } - - fn scan_attribute_value(&self, data: &str) -> usize { - let size = data.len(); - if size == 0 { return 0; } - let open = data.as_bytes()[0]; - let quoted = open == b'\'' || open == b'"'; - let mut i = if quoted { 1 } else { 0 }; - while i < size { - let c = data.as_bytes()[i]; - match c { - b'\n' => { - if !quoted { break; } - let n = self.scan_whitespace_inline(&data[i..]); - if n == 0 { return 0; } - i += n; - } - b'\'' | b'"' | b'=' | b'<' | b'>' | b'`' | b'\t' ... b' ' => { - if !quoted || c == open { break; } - i += 1; - } - _ => i += 1 - } - } - if quoted { - if i == size || data.as_bytes()[i] != open { return 0; } - i += 1; - } - i - } - - fn scan_html_comment(&self, data: &str) -> usize { - if !data.starts_with(""##; - let expected = r##"

    Little header

    -"##; - - use pulldown_cmark::{Parser, html}; - - let mut s = String::new(); - - let p = Parser::new(&original); - html::push_html(&mut s, p); - - assert_eq!(expected, s); -} - -#[test] -fn html_test_5() { - let original = r##"Little header - -
    -

    Useless

    -]]>"##; - let expected = r##"

    Little header

    -