]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #53002 - QuietMisdreavus:brother-may-i-have-some-loops, r=pnkfelix
authorbors <bors@rust-lang.org>
Mon, 6 Aug 2018 01:53:58 +0000 (01:53 +0000)
committerbors <bors@rust-lang.org>
Mon, 6 Aug 2018 01:53:58 +0000 (01:53 +0000)
make `everybody_loops` preserve item declarations

First half of https://github.com/rust-lang/rust/issues/52545.

`everybody_loops` is used by rustdoc to ensure we don't contain erroneous references to platform APIs if one of its uses is pulled in by `#[doc(cfg)]`. However, you can also implement traits for public types inside of functions. This is used by Diesel (probably others, but they were the example that was reported) to get around a recent macro hygiene fix, which has caused their crate to fail to document. While this won't make the traits show up in documentation (that step comes later), it will at least allow files to be generated.

498 files changed:
.travis.yml
COPYRIGHT
RELEASES.md
config.toml.example
src/Cargo.lock
src/Cargo.toml
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/channel.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/ci/docker/dist-various-1/Dockerfile
src/ci/docker/x86_64-gnu-tools/checktools.sh
src/doc/man/rustdoc.1
src/etc/debugger_pretty_printers_common.py
src/etc/gdb_rust_pretty_printing.py
src/liballoc/lib.rs
src/liballoc/task.rs
src/liballoc/vec.rs
src/liballoc_jemalloc/build.rs
src/liballoc_system/lib.rs
src/libcompiler_builtins
src/libcore/alloc.rs
src/libcore/cell.rs
src/libcore/char/decode.rs
src/libcore/char/methods.rs
src/libcore/char/mod.rs
src/libcore/future/future_obj.rs
src/libcore/intrinsics.rs
src/libcore/iter/iterator.rs
src/libcore/manually_drop_stage0.rs [deleted file]
src/libcore/mem.rs
src/libcore/num/dec2flt/parse.rs
src/libcore/num/dec2flt/rawfp.rs
src/libcore/num/diy_float.rs
src/libcore/num/flt2dec/decoder.rs
src/libcore/num/flt2dec/mod.rs
src/libcore/num/flt2dec/strategy/grisu.rs
src/libcore/num/mod.rs
src/libcore/ops/unsize.rs
src/libcore/ptr.rs
src/libcore/slice/memchr.rs
src/libcore/slice/mod.rs
src/libcore/sync/atomic.rs
src/libcore/task/context.rs
src/libcore/task/wake.rs
src/libcore/tests/char.rs
src/libcore/tests/slice.rs
src/libcore/time.rs
src/libcore/unicode/tables.rs
src/libcore/unicode/unicode.py
src/librustc/hir/def.rs
src/librustc/hir/lowering.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/ich/impls_ty.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/lint/levels.rs
src/librustc/lint/mod.rs
src/librustc/middle/cstore.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/entry.rs
src/librustc/middle/reachable.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/traversal.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/select.rs
src/librustc/ty/context.rs
src/librustc/ty/query/config.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/sty.rs
src/librustc/util/profiling.rs [new file with mode: 0644]
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/allocator.rs
src/librustc_codegen_llvm/asm.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_codegen_llvm/back/archive.rs
src/librustc_codegen_llvm/back/link.rs
src/librustc_codegen_llvm/back/linker.rs
src/librustc_codegen_llvm/back/lto.rs
src/librustc_codegen_llvm/back/symbol_export.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/callee.rs
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/consts.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
src/librustc_codegen_llvm/debuginfo/gdb.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/debuginfo/mod.rs
src/librustc_codegen_llvm/debuginfo/namespace.rs
src/librustc_codegen_llvm/debuginfo/source_loc.rs
src/librustc_codegen_llvm/debuginfo/utils.rs
src/librustc_codegen_llvm/declare.rs
src/librustc_codegen_llvm/glue.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/archive_ro.rs [new file with mode: 0644]
src/librustc_codegen_llvm/llvm/diagnostic.rs [new file with mode: 0644]
src/librustc_codegen_llvm/llvm/ffi.rs [new file with mode: 0644]
src/librustc_codegen_llvm/llvm/mod.rs [new file with mode: 0644]
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_llvm/metadata.rs
src/librustc_codegen_llvm/meth.rs
src/librustc_codegen_llvm/mir/analyze.rs
src/librustc_codegen_llvm/mir/block.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/mod.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_codegen_llvm/mir/place.rs
src/librustc_codegen_llvm/mir/rvalue.rs
src/librustc_codegen_llvm/mir/statement.rs
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_llvm/value.rs
src/librustc_codegen_utils/Cargo.toml
src/librustc_codegen_utils/codegen_backend.rs
src/librustc_codegen_utils/lib.rs
src/librustc_codegen_utils/link.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustc_data_structures/bitvec.rs
src/librustc_data_structures/graph/implementation/mod.rs
src/librustc_data_structures/small_vec.rs
src/librustc_data_structures/tiny_list.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_llvm/Cargo.toml
src/librustc_llvm/archive_ro.rs [deleted file]
src/librustc_llvm/build.rs
src/librustc_llvm/diagnostic.rs [deleted file]
src/librustc_llvm/ffi.rs [deleted file]
src/librustc_llvm/lib.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata_utils/Cargo.toml [new file with mode: 0644]
src/librustc_metadata_utils/lib.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/escaping_locals.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/liveness_map.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/type_check/liveness.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/dataflow/impls/borrowed_locals.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/terminator/drop.rs
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/remove_noop_landing_pads.rs
src/librustc_mir/transform/simplify.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_passes/ast_validation.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/lib.rs
src/librustc_target/abi/call/mod.rs
src/librustc_target/abi/call/riscv.rs [new file with mode: 0644]
src/librustc_target/lib.rs
src/librustc_target/spec/aarch64_unknown_hermit.rs [new file with mode: 0644]
src/librustc_target/spec/hermit_base.rs [new file with mode: 0644]
src/librustc_target/spec/mod.rs
src/librustc_target/spec/riscv32imac_unknown_none_elf.rs [new file with mode: 0644]
src/librustc_target/spec/x86_64_unknown_hermit.rs [new file with mode: 0644]
src/librustc_typeck/check/mod.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs [new file with mode: 0644]
src/librustdoc/clean/def_ctor.rs [new file with mode: 0644]
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/simplify.rs
src/librustdoc/core.rs
src/librustdoc/externalfiles.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/passes/collapse_docs.rs
src/librustdoc/passes/collect_intra_doc_links.rs [new file with mode: 0644]
src/librustdoc/passes/mod.rs
src/librustdoc/passes/propagate_doc_cfg.rs
src/librustdoc/passes/strip_hidden.rs
src/librustdoc/passes/strip_priv_imports.rs
src/librustdoc/passes/strip_private.rs
src/librustdoc/passes/unindent_comments.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/librustdoc/visit_lib.rs
src/libserialize/serialize.rs
src/libstd/Cargo.toml
src/libstd/alloc.rs
src/libstd/ascii.rs
src/libstd/ffi/c_str.rs
src/libstd/ffi/os_str.rs
src/libstd/future.rs
src/libstd/io/buffered.rs
src/libstd/io/cursor.rs
src/libstd/io/mod.rs
src/libstd/macros.rs
src/libstd/os/hermit/fs.rs [new file with mode: 0644]
src/libstd/os/hermit/mod.rs [new file with mode: 0644]
src/libstd/os/hermit/raw.rs [new file with mode: 0644]
src/libstd/os/mod.rs
src/libstd/sync/once.rs
src/libstd/sys/unix/args.rs
src/libstd/sys/unix/condvar.rs
src/libstd/sys/unix/env.rs
src/libstd/sys/unix/fast_thread_local.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/time.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/thread.rs
src/libstd/thread/mod.rs
src/libstd_unicode/Cargo.toml [deleted file]
src/libstd_unicode/lib.rs [deleted file]
src/libsyntax/ast.rs
src/libsyntax/attr/mod.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/token.rs
src/libsyntax_ext/format_foreign.rs
src/libsyntax_pos/hygiene.rs
src/llvm
src/rustllvm/ArchiveWrapper.cpp
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/rustllvm/llvm-rebuild-trigger
src/stage0.txt
src/test/codegen/slice-position-bounds-check.rs [new file with mode: 0644]
src/test/codegen/sparc-struct-abi.rs
src/test/codegen/vec-clear.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/issue-52489.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs [new file with mode: 0644]
src/test/compile-fail/const-err4.rs
src/test/compile-fail/feature-gate-tool_attributes.rs [deleted file]
src/test/compile-fail/issue-52489.rs [new file with mode: 0644]
src/test/compile-fail/lto-duplicate-symbols.rs [new file with mode: 0644]
src/test/compile-fail/unknown-tool-name.rs
src/test/compile-fail/unknown_tool_attributes-1.rs [deleted file]
src/test/run-make-fulldeps/exit-code/lint-failure.rs
src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
src/test/run-make-fulldeps/issue-19371/foo.rs
src/test/run-pass-fulldeps/compiler-calls.rs
src/test/run-pass-fulldeps/proc-macro/issue-42708.rs
src/test/run-pass-fulldeps/proc-macro/issue-50061.rs
src/test/run-pass/auxiliary/issue_38715-modern.rs [new file with mode: 0644]
src/test/run-pass/const-endianess.rs
src/test/run-pass/generator/yield-in-initializer.rs [new file with mode: 0644]
src/test/run-pass/issue-38715.rs
src/test/run-pass/issue-52557.rs [new file with mode: 0644]
src/test/rustdoc-ui/failed-doctest-output.stdout
src/test/rustdoc-ui/intra-doc-alias-ice.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc-alias-ice.stderr [new file with mode: 0644]
src/test/rustdoc/auxiliary/intra-link-extern-crate.rs [new file with mode: 0644]
src/test/rustdoc/generic-impl.rs
src/test/rustdoc/intra-link-extern-crate.rs [new file with mode: 0644]
src/test/rustdoc/intra-link-private.rs [new file with mode: 0644]
src/test/rustdoc/primitive-generic-impl.rs [new file with mode: 0644]
src/test/rustdoc/primitive/primitive-generic-impl.rs [new file with mode: 0644]
src/test/ui-fulldeps/auxiliary/lint_tool_test.rs [new file with mode: 0644]
src/test/ui-fulldeps/lint_tool_test.rs [new file with mode: 0644]
src/test/ui-fulldeps/lint_tool_test.stderr [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/parent-source-spans.rs
src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs [new file with mode: 0644]
src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed [new file with mode: 0644]
src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs [new file with mode: 0644]
src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr [new file with mode: 0644]
src/test/ui/asm-out-assign-imm.nll.stderr
src/test/ui/asm-out-assign-imm.rs
src/test/ui/asm-out-assign-imm.stderr
src/test/ui/async-matches-expr.rs [new file with mode: 0644]
src/test/ui/auxiliary/macro-in-other-crate.rs
src/test/ui/borrowck/borrowck-closures-two-mut.stderr
src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr
src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr
src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
src/test/ui/borrowck/issue-41962.stderr
src/test/ui/borrowck/issue-51415.nll.stderr
src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs [new file with mode: 0644]
src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr
src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.nll.stderr
src/test/ui/borrowck/two-phase-multi-mut.stderr
src/test/ui/codemap_tests/overlapping_spans.nll.stderr
src/test/ui/const-eval/simple_with_undef.rs [new file with mode: 0644]
src/test/ui/const-eval/union-const-eval-field.rs
src/test/ui/const-eval/union-const-eval-field.stderr
src/test/ui/const-eval/union-ice.rs
src/test/ui/const-eval/union-ice.stderr
src/test/ui/did_you_mean/issue-39544.nll.stderr
src/test/ui/duplicate-check-macro-exports.rs
src/test/ui/duplicate-check-macro-exports.stderr
src/test/ui/error-codes/E0504.nll.stderr
src/test/ui/feature-gate-macros_in_extern.stderr
src/test/ui/feature-gate-tool_attributes.rs
src/test/ui/feature-gate-tool_attributes.stderr
src/test/ui/generator/dropck.nll.stderr
src/test/ui/hygiene/fields-move.nll.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
src/test/ui/imports/local-modularized-tricky-fail-1.rs [new file with mode: 0644]
src/test/ui/imports/local-modularized-tricky-fail-1.stderr [new file with mode: 0644]
src/test/ui/imports/local-modularized-tricky-fail-2.rs [new file with mode: 0644]
src/test/ui/imports/local-modularized-tricky-fail-2.stderr [new file with mode: 0644]
src/test/ui/imports/local-modularized-tricky-pass.rs [new file with mode: 0644]
src/test/ui/imports/local-modularized.rs [new file with mode: 0644]
src/test/ui/issue-10291.nll.stderr
src/test/ui/issue-11192.nll.stderr
src/test/ui/issue-11692-1.rs
src/test/ui/issue-11692-1.stderr
src/test/ui/issue-11692-2.rs
src/test/ui/issue-11692-2.stderr
src/test/ui/issue-11873.nll.stderr
src/test/ui/issue-12567.nll.stderr
src/test/ui/issue-18783.nll.stderr
src/test/ui/issue-24357.nll.stderr
src/test/ui/issue-27282-move-match-input-into-guard.stderr
src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr
src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr
src/test/ui/issue-27592.nll.stderr
src/test/ui/issue-4335.nll.stderr
src/test/ui/issue-45696-long-live-borrows-in-boxes.rs [new file with mode: 0644]
src/test/ui/issue-45696-no-variant-box-recur.rs [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.ast.stderr [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.migrate.stderr [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.nll.stderr [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.rs [new file with mode: 0644]
src/test/ui/issue-49579.rs [new file with mode: 0644]
src/test/ui/issue-49824.nll.stderr [new file with mode: 0644]
src/test/ui/issue-49824.rs [new file with mode: 0644]
src/test/ui/issue-49824.stderr [new file with mode: 0644]
src/test/ui/issue-50187.rs
src/test/ui/issue-52126-assign-op-invariance.nll.stderr
src/test/ui/issue-52213.nll.stderr
src/test/ui/issue-6801.nll.stderr
src/test/ui/lint/unused_parens_json_suggestion.stderr
src/test/ui/macro-path-prelude-fail-1.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-1.stderr [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-2.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-2.stderr [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-3.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-3.stderr [new file with mode: 0644]
src/test/ui/macro-path-prelude-pass.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-shadowing.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-shadowing.stderr [new file with mode: 0644]
src/test/ui/macros/format-foreign.rs
src/test/ui/macros/format-foreign.stderr
src/test/ui/macros/format-unused-lables.stderr
src/test/ui/macros/trace-macro.stderr
src/test/ui/nll/closure-access-spans.rs [new file with mode: 0644]
src/test/ui/nll/closure-access-spans.stderr [new file with mode: 0644]
src/test/ui/nll/closure-borrow-spans.rs [new file with mode: 0644]
src/test/ui/nll/closure-borrow-spans.stderr [new file with mode: 0644]
src/test/ui/nll/closure-captures.rs
src/test/ui/nll/closure-move-spans.rs [new file with mode: 0644]
src/test/ui/nll/closure-move-spans.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
src/test/ui/nll/closure-use-spans.rs [new file with mode: 0644]
src/test/ui/nll/closure-use-spans.stderr [new file with mode: 0644]
src/test/ui/nll/closures-in-loops.rs [new file with mode: 0644]
src/test/ui/nll/closures-in-loops.stderr [new file with mode: 0644]
src/test/ui/nll/extra-unused-mut.rs
src/test/ui/nll/get_default.nll.stderr
src/test/ui/nll/get_default.stderr
src/test/ui/nll/issue-51268.stderr
src/test/ui/nll/issue-52113.rs [new file with mode: 0644]
src/test/ui/nll/issue-52113.stderr [new file with mode: 0644]
src/test/ui/nll/issue-52133.rs [deleted file]
src/test/ui/nll/issue-52133.stderr [deleted file]
src/test/ui/nll/mir_check_cast_closure.stderr
src/test/ui/nll/mir_check_cast_unsize.stderr
src/test/ui/nll/move-errors.stderr
src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs [new file with mode: 0644]
src/test/ui/nll/return-ref-mut-issue-46557.stderr
src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
src/test/ui/region-borrow-params-issue-29793-small.nll.stderr
src/test/ui/regions-nested-fns-2.nll.stderr
src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr
src/test/ui/rust-2018/macro-use-warned-against.rs
src/test/ui/rust-2018/macro-use-warned-against.stderr
src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
src/test/ui/span/dropck-object-cycle.nll.stderr
src/test/ui/span/dropck_arr_cycle_checked.nll.stderr
src/test/ui/span/dropck_vec_cycle_checked.nll.stderr
src/test/ui/span/mut-arg-hint.nll.stderr
src/test/ui/span/range-2.nll.stderr
src/test/ui/span/regions-escape-loop-via-variable.nll.stderr
src/test/ui/span/regions-escape-loop-via-vec.nll.stderr
src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
src/test/ui/span/vec_refs_data_with_early_death.nll.stderr
src/test/ui/target-feature-gate.rs
src/test/ui/target-feature-gate.stderr
src/test/ui/target-feature-wrong.rs
src/test/ui/target-feature-wrong.stderr
src/test/ui/tool-attributes-disabled-1.rs [new file with mode: 0644]
src/test/ui/tool-attributes-disabled-1.stderr [new file with mode: 0644]
src/test/ui/tool-attributes-disabled-2.rs [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-1.rs [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-1.stderr [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-2.rs [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-2.stderr [new file with mode: 0644]
src/test/ui/tool-attributes-shadowing.rs [new file with mode: 0644]
src/test/ui/tool-attributes-shadowing.stderr [new file with mode: 0644]
src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clippy
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs
src/tools/error_index_generator/main.rs
src/tools/lld
src/tools/rls
src/tools/rustc-workspace-hack/Cargo.toml [new file with mode: 0644]
src/tools/rustc-workspace-hack/README.md [new file with mode: 0644]
src/tools/rustc-workspace-hack/lib.rs [new file with mode: 0644]
src/tools/rustfmt

index 0228fdc994dd769b5512c55a074dafd2dcffddd1..a860aaa5b7e6b0becc86e9bda37fb674203bbe0d 100644 (file)
@@ -218,6 +218,10 @@ before_install:
       echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json;
       sudo service docker restart;
     fi
+  - date
+  - sudo atq || true
+  - sudo grep -rE 'shutdown|poweroff|halt' /var/spool/cron || true
+  - sudo grep -E 'google-clock-skew|ntpd|startup-script' /var/log/syslog || true
 
 install:
   - case "$TRAVIS_OS_NAME" in
index 9bc018d983d7d7822cda2149245cc5eb08e3292b..e2d0ed77224e3d8344da35984bf03cf0088cfc1a 100644 (file)
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -10,8 +10,8 @@ Copyrights in the Rust project are retained by their contributors. No
 copyright assignment is required to contribute to the Rust project.
 
 Some files include explicit copyright notices and/or license notices.
-For full authorship information, see AUTHORS.txt and the version control
-history.
+For full authorship information, see the version control history or
+https://thanks.rust-lang.org
 
 Except as otherwise noted (below and/or in individual files), Rust is
 licensed under the Apache License, Version 2.0 <LICENSE-APACHE> or
index b983851f881987a11089e8409ca0c5666e378c5f..1f7ffb53d3cadcfcb6811da4cafcc7583b5c276a 100644 (file)
@@ -94,9 +94,9 @@ Misc
 
 Compatibility Notes
 -------------------
-- [Rust will no longer consider trait objects with duplicated constraints to
-  have implementations.][51276] For example the below code will now fail
-  to compile.
+- [Rust will consider trait objects with duplicated constraints to be the same
+  type as without the duplicated constraint.][51276] For example the below code will
+  now fail to compile.
   ```rust
   trait Trait {}
 
@@ -144,7 +144,7 @@ Compatibility Notes
 [`alloc::handle_alloc_error`]: https://doc.rust-lang.org/std/alloc/fn.handle_alloc_error.html
 [`btree_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default
 [`fmt::Alignment`]: https://doc.rust-lang.org/std/fmt/enum.Alignment.html
-[`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default
+[`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_default
 [`iter::repeat_with`]: https://doc.rust-lang.org/std/iter/fn.repeat_with.html
 [`num::NonZeroUsize`]: https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html
 [`num::NonZeroU128`]: https://doc.rust-lang.org/std/num/struct.NonZeroU128.html
@@ -160,6 +160,17 @@ Compatibility Notes
 [`{Any + Send + Sync}::downcast_ref`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-2
 [`{Any + Send + Sync}::is`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.is-2
 
+Version 1.27.2 (2018-07-20)
+===========================
+
+Compatibility Notes
+-------------------
+
+- The borrow checker was fixed to avoid potential unsoundness when using
+  match ergonomics: [#52213][52213].
+
+[52213]: https://github.com/rust-lang/rust/issues/52213
+
 Version 1.27.1 (2018-07-10)
 ===========================
 
@@ -190,7 +201,7 @@ Version 1.27.0 (2018-06-21)
 Language
 --------
 - [Removed 'proc' from the reserved keywords list.][49699] This allows `proc` to
-  be used as an identifer.
+  be used as an identifier.
 - [The dyn syntax is now available.][49968] This syntax is equivalent to the
   bare `Trait` syntax, and should make it clearer when being used in tandem with
   `impl Trait`. Since it is equivalent to the following syntax:
@@ -205,7 +216,7 @@ Language
 
 Compiler
 --------
-- [Added the `armv5te-unknown-linux-musl` target.][50423]
+- [Added the `armv5te-unknown-linux-musleabi` target.][50423]
 
 Libraries
 ---------
@@ -4795,7 +4806,7 @@ Language
 --------
 
 * Patterns with `ref mut` now correctly invoke [`DerefMut`] when
-  matching against dereferencable values.
+  matching against dereferenceable values.
 
 Libraries
 ---------
index 99073416334f59ef7b02fcae69c7ac276c3084d3..eb7cd61a1b07e7a936e126db5f9e622421d291a5 100644 (file)
@@ -61,8 +61,8 @@
 # the same format as above, but since these targets are experimental, they are
 # not built by default and the experimental Rust compilation targets that depend
 # on them will not work unless the user opts in to building them. By default the
-# `WebAssembly` target is enabled when compiling LLVM from scratch.
-#experimental-targets = "WebAssembly"
+# `WebAssembly` and `RISCV` targets are enabled when compiling LLVM from scratch.
+#experimental-targets = "WebAssembly;RISCV"
 
 # Cap the number of parallel linker invocations when compiling LLVM.
 # This can be useful when building LLVM with debug info, which significantly
index 89daa8e09c7d1327b0c4f813be1408430b245bb3..7c57cf32d1b14448323ac54edbf321aaad03a5cd 100644 (file)
@@ -80,8 +80,8 @@ dependencies = [
  "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -183,7 +183,7 @@ dependencies = [
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -226,11 +226,11 @@ dependencies = [
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "crates-io 0.18.0",
- "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.5.0 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -247,9 +247,9 @@ dependencies = [
  "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-workspace-hack 1.0.0",
+ "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 1.0.2 (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.70 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -351,20 +351,18 @@ name = "clippy"
 version = "0.0.212"
 dependencies = [
  "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.5.8 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-workspace-hack 1.0.0",
  "rustc_version 0.2.2 (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.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -452,7 +450,7 @@ dependencies = [
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -521,7 +519,7 @@ version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -533,7 +531,7 @@ name = "crates-io"
 version = "0.18.0"
 dependencies = [
  "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -606,6 +604,11 @@ name = "crossbeam-utils"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "crossbeam-utils"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "crypto-hash"
 version = "0.3.1"
@@ -763,21 +766,22 @@ dependencies = [
 
 [[package]]
 name = "failure"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "failure_derive"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1766,14 +1770,14 @@ dependencies = [
 
 [[package]]
 name = "rls"
-version = "0.129.0"
+version = "0.130.2"
 dependencies = [
  "cargo 0.30.0",
  "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy_lints 0.0.212",
  "crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.45.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1787,10 +1791,11 @@ dependencies = [
  "rls-analysis 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-rustc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.9.0",
+ "rustc-workspace-hack 1.0.0",
+ "rustfmt-nightly 0.99.1",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1830,7 +1835,7 @@ dependencies = [
 
 [[package]]
 name = "rls-rustc"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1848,7 +1853,6 @@ name = "rls-vfs"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "racer 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1899,6 +1903,14 @@ dependencies = [
  "rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-arena"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
 version = "209.0.0"
@@ -1908,6 +1920,15 @@ dependencies = [
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_cratesio_shim"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-rustc_data_structures"
 version = "209.0.0"
@@ -1926,6 +1947,24 @@ dependencies = [
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_data_structures"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.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.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.1 (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 = "209.0.0"
@@ -1939,6 +1978,19 @@ dependencies = [
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_errors"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 0.3.6 (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_target"
 version = "209.0.0"
@@ -1950,11 +2002,27 @@ dependencies = [
  "rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_target"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-serialize"
 version = "209.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "rustc-ap-serialize"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "rustc-ap-syntax"
 version = "209.0.0"
@@ -1970,6 +2038,21 @@ dependencies = [
  "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-syntax"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-syntax_pos"
 version = "209.0.0"
@@ -1983,6 +2066,19 @@ dependencies = [
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-syntax_pos"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-arena 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.2 (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.8"
@@ -2030,6 +2126,14 @@ name = "rustc-serialize"
 version = "0.3.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "rustc-workspace-hack"
+version = "1.0.0"
+dependencies = [
+ "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc_allocator"
 version = "0.0.0"
@@ -2115,6 +2219,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_incremental 0.0.0",
+ "rustc_metadata_utils 0.0.0",
  "rustc_mir 0.0.0",
  "rustc_target 0.0.0",
  "syntax 0.0.0",
@@ -2222,11 +2327,8 @@ dependencies = [
 name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_helper 0.1.0",
  "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_cratesio_shim 0.0.0",
 ]
 
 [[package]]
@@ -2251,6 +2353,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_metadata_utils 0.0.0",
  "rustc_target 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
@@ -2258,6 +2361,15 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "rustc_metadata_utils"
+version = "0.0.0"
+dependencies = [
+ "rustc 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
 [[package]]
 name = "rustc_mir"
 version = "0.0.0"
@@ -2340,6 +2452,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_metadata 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2441,10 +2554,10 @@ dependencies = [
 
 [[package]]
 name = "rustfix"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2453,23 +2566,23 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.9.0"
+version = "0.99.1"
 dependencies = [
  "assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2615,18 +2728,9 @@ dependencies = [
  "rustc_lsan 0.0.0",
  "rustc_msan 0.0.0",
  "rustc_tsan 0.0.0",
- "std_unicode 0.0.0",
  "unwind 0.0.0",
 ]
 
-[[package]]
-name = "std_unicode"
-version = "0.0.0"
-dependencies = [
- "compiler_builtins 0.0.0",
- "core 0.0.0",
-]
-
 [[package]]
 name = "string_cache"
 version = "0.7.3"
@@ -2718,11 +2822,13 @@ dependencies = [
 
 [[package]]
 name = "synstructure"
-version = "0.6.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3131,6 +3237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-epoch 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "285987a59c4d91388e749850e3cb7b3a92299668528caaacd08005b8f238c0ea"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea52fab26a99d96cdff39d0ca75c9716125937f5dba2ab83923aaaf5928f684a"
+"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
 "checksum curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "893713db705eab9847e050268507b0e2a2aad64e90a831874bd4e8e0d67f9523"
 "checksum curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "de9cf174efdf90b5887c4e2e900769373c89c5e18152e8f3ed75b501a6f1c0fb"
@@ -3147,8 +3254,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
-"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
-"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
+"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"
+"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
 "checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f"
 "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
@@ -3256,24 +3363,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-analysis 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96f84d303dcbe1c1bdd41b10867d3399c38fbdac32c4e3645cdb6dbd7f82db1d"
 "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2"
 "checksum rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd20763e1c60ae8945384c8a8fa4ac44f8afa7b0a817511f5e8927e5d24f988"
-"checksum rls-rustc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c8c09117ae2887baaa4b17fe1cb572f9b22e4d2c6a5cda04093d8b366b0be99"
+"checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecbc8541b4c341d6271eae10f869dd9d36db871afe184f5b6f9bffbd6ed0373f"
 "checksum rustc-ap-arena 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b098827864368459cbc7a79fbc54eafb92df7e00a46c0cda352b5a21583ee436"
+"checksum rustc-ap-arena 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eec75ed880706dd9a05bc770c327ed142fa7d4b648d9757fbc71d821d68448a5"
 "checksum rustc-ap-rustc_cratesio_shim 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4d923dea14fb085bca743fb982f6a3bc11c0d5d30b822bcf6fa16e9464a56c"
+"checksum rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f5d54615bedbae65a976e0835edf0de90dd962ec818c0149fe181d5cd81da9e"
 "checksum rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c6a5c9edc6b4ae035cdc03af7d8662d39fad7879c5501d103e7087dfaebc80"
+"checksum rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c51cc6e79eab25c7ea84a7e104e81e6f44cca32709df54c2cdb4e7059d7843"
 "checksum rustc-ap-rustc_errors 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1e9bdc597abd95cebce0c14c1da58943a9e5b8255530a0fec30659d144eb0b"
+"checksum rustc-ap-rustc_errors 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff050095b7afb254506591ee7d3a5d0fb9c03c16f8c2741b588178085e563d49"
 "checksum rustc-ap-rustc_target 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142ddef3dc12dda2bcd3412f0d96d3745413a8fbc2f224f0cc97afa04c071d89"
+"checksum rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53c7a8c21c3b05f24998fa6ab9ded6269810a2f3ae12ff301c432c1e9fa8e111"
 "checksum rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b08f8f175b038a82caa7e51fc52b72ff96cfe8c1429755da30380dbd4199c7f"
+"checksum rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4713c2c0c26a45ead8fb16fee88e16fecf999588ae6920847cbaeb19565b7f"
 "checksum rustc-ap-syntax 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c802e0e1fbc64eddc21e0798527eb1f5fdbd5781d119bd2c44b6130afdc81cc"
+"checksum rustc-ap-syntax 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "768e2698f912913be2ccd355b2dea62c978efc356f75db1400605f3642905d53"
 "checksum rustc-ap-syntax_pos 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "008d47cc54ed12a2784217b9e6630a7fa1c8dc3591a283f65ad4b7fa307d49d5"
+"checksum rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a280dc8919aa7f684832ba3eeab2f6c96dbe2e2e4f6a922f7f0bdb3a9dd9e641"
 "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
 "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
-"checksum rustfix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86f77b09d42bae4adfbcd105a8914e2d9fb46b63612c1a765b824a2b4a4bb814"
+"checksum rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "756567f00f7d89c9f89a5c401b8b1caaa122e27240b9eaadd0bb52ee0b680b1b"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
 "checksum schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1fabf2a7b6483a141426e1afd09ad543520a77ac49bd03c286e7696ccfd77f"
 "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
@@ -3300,7 +3415,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b"
 "checksum syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2beff8ebc3658f07512a413866875adddd20f4fd47b2a4e6c9da65cd281baaea"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
+"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
 "checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a"
 "checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b"
 "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
index 62403700f3a4010a9acf93754a59bdfdffb2a00e..01663487f92e12459857cecd4135d2272d2bfa14 100644 (file)
@@ -52,11 +52,15 @@ debug-assertions = false
 [patch."https://github.com/rust-lang/cargo"]
 cargo = { path = "tools/cargo" }
 
-[patch."https://github.com/rust-lang-nursery/rustfmt"]
+[patch.crates-io]
 # Similar to Cargo above we want the RLS to use a vendored version of `rustfmt`
 # that we're shipping as well (to ensure that the rustfmt in RLS and the
 # `rustfmt` executable are the same exact version).
 rustfmt-nightly = { path = "tools/rustfmt" }
 
+# See comments in `tools/rustc-workspace-hack/README.md` for what's going on
+# here
+rustc-workspace-hack = { path = 'tools/rustc-workspace-hack' }
+
 [patch."https://github.com/rust-lang-nursery/rust-clippy"]
 clippy_lints = { path = "tools/clippy/clippy_lints" }
index 71c1c61e3d97ebd51e9bd8cf5b9946cbcbe5ca5c..829487163a945ec21f9850c997901520105ec9b4 100644 (file)
@@ -88,7 +88,10 @@ def _download(path, url, probably_big, verbose, exception):
             option = "-#"
         else:
             option = "-s"
-        run(["curl", option, "--retry", "3", "-Sf", "-o", path, url],
+        run(["curl", option,
+             "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
+             "--connect-timeout", "30", # timeout if cannot connect within 30 seconds
+             "--retry", "3", "-Sf", "-o", path, url],
             verbose=verbose,
             exception=exception)
 
index 724d3b741903ff6ffc21e17838be60bf38155a15..dc0b0aaf0bb3c894802f18be4d2e21e94b11a57c 100644 (file)
@@ -777,7 +777,7 @@ pub fn cargo(
         // compiler, but for tools we just use the precompiled libraries that
         // we've downloaded
         let use_snapshot = mode == Mode::ToolBootstrap;
-        assert!(!use_snapshot || stage == 0);
+        assert!(!use_snapshot || stage == 0 || self.local_rebuild);
 
         let maybe_sysroot = self.sysroot(compiler);
         let sysroot = if use_snapshot {
index 04d576df95546b98d58bac8316e69ae280b221d0..fa2b58fb2daa711714407124900514f49798d31b 100644 (file)
@@ -24,7 +24,7 @@
 use config::Config;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.29.0";
+pub const CFG_RELEASE_NUM: &str = "1.30.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
index 04e8e133b03a11ffca2991a1eb639524b413cc41..8c4f2df60fe6ff1ca0f7576bb91365613987504a 100644 (file)
@@ -157,7 +157,6 @@ pub fn std_cargo(builder: &Builder,
         cargo.arg("--features").arg("c mem")
             .args(&["-p", "alloc"])
             .args(&["-p", "compiler_builtins"])
-            .args(&["-p", "std_unicode"])
             .arg("--manifest-path")
             .arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml"));
     } else {
index 0a8a5c87d0da1a4b1a90cbd5aad26b634f02ae34..1a94d597ef895d6e5ba8b0cdc0ceab073ca1ffec 100644 (file)
@@ -507,7 +507,7 @@ pub fn parse(args: &[String]) -> Config {
             set(&mut config.llvm_link_shared, llvm.link_shared);
             config.llvm_targets = llvm.targets.clone();
             config.llvm_experimental_targets = llvm.experimental_targets.clone()
-                .unwrap_or("WebAssembly".to_string());
+                .unwrap_or("WebAssembly;RISCV".to_string());
             config.llvm_link_jobs = llvm.link_jobs;
             config.llvm_clang_cl = llvm.clang_cl.clone();
         }
index c6b39a52ae135ee311fb19eb720d2acd1f54dd1d..188e64cd668ddc6bb2bdc68c34051254656d1a7a 100644 (file)
@@ -856,7 +856,6 @@ fn run(self, builder: &Builder) -> PathBuf {
             "src/librustc_msan",
             "src/librustc_tsan",
             "src/libstd",
-            "src/libstd_unicode",
             "src/libunwind",
             "src/rustc/compiler_builtins_shim",
             "src/rustc/libc_shim",
index 9dbbe6bcfe490eaf0a8408574dfb32b3782a1585..ed9b5b1773fae0de01342200b363505902394a12 100644 (file)
@@ -489,7 +489,7 @@ fn run(self, builder: &Builder) {
         // Keep a whitelist so we do not build internal stdlib crates, these will be
         // build by the rustc step later if enabled.
         cargo.arg("--no-deps");
-        for krate in &["alloc", "core", "std", "std_unicode"] {
+        for krate in &["alloc", "core", "std"] {
             cargo.arg("-p").arg(krate);
             // Create all crate output directories first to make sure rustdoc uses
             // relative links.
index 6a013053e580c78f8a26f1b6e105c7960073b65f..60b4d65f444014133bd81262a7cbdcabea84bdfe 100644 (file)
@@ -121,7 +121,10 @@ pub fn parse(args: &[String]) -> Flags {
         opts.optmulti("", "exclude", "build paths to exclude", "PATH");
         opts.optopt("", "on-fail", "command to run on failure", "CMD");
         opts.optflag("", "dry-run", "dry run; don't build anything");
-        opts.optopt("", "stage", "stage to build", "N");
+        opts.optopt("", "stage",
+            "stage to build (indicates compiler to use/test, e.g. stage 0 uses the \
+             bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
+            "N");
         opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling", "N");
         opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
         opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
@@ -258,7 +261,7 @@ pub fn parse(args: &[String]) -> Flags {
 
         ./x.py build --stage 1 src/libtest
 
-    This will first build everything once (like --stage 0 without further
+    This will first build everything once (like `--stage 0` without further
     arguments would), and then use the compiler built in stage 0 to build
     src/libtest and its dependencies.
     Once this is done, build/$ARCH/stage1 contains a usable compiler.",
@@ -290,10 +293,14 @@ pub fn parse(args: &[String]) -> Flags {
 
         ./x.py test src/test/run-pass
         ./x.py test src/libstd --test-args hash_map
-        ./x.py test src/libstd --stage 0
+        ./x.py test src/libstd --stage 0 --no-doc
         ./x.py test src/test/ui --bless
         ./x.py test src/test/ui --compare-mode nll
 
+    Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`;
+    just like `build src/libstd --stage N` it tests the compiler produced by the previous
+    stage.
+
     If no arguments are passed then the complete artifacts for that stage are
     compiled and tested.
 
index 24a1dbbde66396c756df043a78cc62974fe27ad0..c86010379f495fe56e89a31ff1eed0106bd5a513 100644 (file)
@@ -298,6 +298,8 @@ fn run(self, builder: &Builder) {
         cargo.env("RLS_TEST_WORKSPACE_DIR", test_workspace_path);
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.arg("--")
+            .args(builder.config.cmd.test_args());
 
         if try_run(builder, &mut cargo) {
             builder.save_toolstate("rls", ToolState::TestPass);
index 5e68b797b3d54fe4a80b7e8a5724e410e29e6a12..eaa316494477e73eb6ac8934fb22c6bd4c96a0c6 100644 (file)
@@ -221,6 +221,10 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
                          prev.0, &prev_features - &cur_features, prev.1);
             }
             println!("");
+            println!("to fix this you will probably want to edit the local \
+                      src/tools/rustc-workspace-hack/Cargo.toml crate, as \
+                      that will update the dependency graph to ensure that \
+                      these crates all share the same feature set");
             panic!("tools should not compile multiple copies of the same crate");
         }
 
index 6302f550091ad6285df2584ed6a26022f462cf18..bfc5e712f76c3aa1802e5a66fe45472454728b9b 100644 (file)
@@ -102,6 +102,7 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
+ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
 
 ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
index 16055078ad5eb1bec918b509971a513f7c218783..d876cb7f37a41b91dea2148a05f95818f55bb8ae 100755 (executable)
@@ -17,9 +17,11 @@ TOOLSTATE_FILE="$(realpath $2)"
 OS="$3"
 COMMIT="$(git rev-parse HEAD)"
 CHANGED_FILES="$(git diff --name-status HEAD HEAD^)"
-SIX_WEEK_CYCLE="$(( ($(date +%s) / 604800 - 3) % 6 ))"
-# ^ 1970 Jan 1st is a Thursday, and our release dates are also on Thursdays,
-#   thus we could divide by 604800 (7 days in seconds) directly.
+SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))"
+# ^ Number of days after the last promotion of beta.
+#   Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens.
+#   The Wednesday after this has value 0.
+#   We track this value to prevent regressing tools in the last week of the 6-week cycle.
 
 touch "$TOOLSTATE_FILE"
 
@@ -98,7 +100,7 @@ change_toolstate() {
     if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then
         echo 'Toolstate is not changed. Not updating.'
     else
-        if [ $SIX_WEEK_CYCLE -eq 5 ]; then
+        if [ $SIX_WEEK_CYCLE -ge 35 ]; then
             python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed
         fi
         sed -i "1 a\\
index a878380f556b3f069f7512c29e54de33110a40da..d7f78e8f6f4de7ddf10e6547932ada586e2a319b 100644 (file)
@@ -119,7 +119,7 @@ See <\fBhttps://github.com/rust\-lang/rust/issues\fR>
 for issues.
 
 .SH "AUTHOR"
-See \fIAUTHORS.txt\fR in the Rust source distribution.
+See the version control history or <\fBhttps://thanks.rust\-lang.org\fR>
 
 .SH "COPYRIGHT"
 This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms.
index 4a38d4be083fdcac5202d1dcd3c6431c2d968caf..87c7b21bb8a35f20110ba9bc44c653586fc1aba8 100644 (file)
@@ -47,6 +47,7 @@ TYPE_KIND_PTR               = 15
 TYPE_KIND_FIXED_SIZE_VEC    = 16
 TYPE_KIND_REGULAR_UNION     = 17
 TYPE_KIND_OS_STRING         = 18
+TYPE_KIND_STD_VECDEQUE      = 19
 
 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
 ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
@@ -62,6 +63,14 @@ STD_VEC_FIELD_NAME_BUF = "buf"
 STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF,
                        STD_VEC_FIELD_NAME_LENGTH]
 
+# std::collections::VecDeque<> related constants
+STD_VECDEQUE_FIELD_NAME_TAIL = "tail"
+STD_VECDEQUE_FIELD_NAME_HEAD = "head"
+STD_VECDEQUE_FIELD_NAME_BUF = "buf"
+STD_VECDEQUE_FIELD_NAMES = [STD_VECDEQUE_FIELD_NAME_TAIL,
+                            STD_VECDEQUE_FIELD_NAME_HEAD,
+                            STD_VECDEQUE_FIELD_NAME_BUF]
+
 # std::String related constants
 STD_STRING_FIELD_NAMES = ["vec"]
 
@@ -161,6 +170,11 @@ class Type(object):
             self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)):
             return TYPE_KIND_STD_VEC
 
+        # STD COLLECTION VECDEQUE
+        if (unqualified_type_name.startswith("VecDeque<") and
+            self.__conforms_to_field_layout(STD_VECDEQUE_FIELD_NAMES)):
+            return TYPE_KIND_STD_VECDEQUE
+
         # STD STRING
         if (unqualified_type_name.startswith("String") and
             self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
@@ -325,6 +339,25 @@ def extract_length_ptr_and_cap_from_std_vec(vec_val):
     assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
     return (length, data_ptr, capacity)
 
+
+def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val):
+    assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VECDEQUE
+    tail_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_TAIL)
+    head_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_HEAD)
+    buf_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_BUF)
+
+    tail = vec_val.get_child_at_index(tail_field_index).as_integer()
+    head = vec_val.get_child_at_index(head_field_index).as_integer()
+    buf = vec_val.get_child_at_index(buf_field_index)
+
+    vec_ptr_val = buf.get_child_at_index(0)
+    capacity = buf.get_child_at_index(1).as_integer()
+    unique_ptr_val = vec_ptr_val.get_child_at_index(0)
+    data_ptr = unique_ptr_val.get_child_at_index(0)
+    assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
+    return (tail, head, data_ptr, capacity)
+
+
 def extract_length_and_ptr_from_slice(slice_val):
     assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
             slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
index 0612873e28153b445964ccaffb52021098ddf915..b7de42a93841757abc7e8e815d01c24632f9a334 100755 (executable)
@@ -124,6 +124,9 @@ def rust_pretty_printer_lookup_function(gdb_val):
     if type_kind == rustpp.TYPE_KIND_STD_VEC:
         return RustStdVecPrinter(val)
 
+    if type_kind == rustpp.TYPE_KIND_STD_VECDEQUE:
+        return RustStdVecDequePrinter(val)
+
     if type_kind == rustpp.TYPE_KIND_STD_STRING:
         return RustStdStringPrinter(val)
 
@@ -274,6 +277,28 @@ class RustStdVecPrinter(object):
             yield (str(index), (gdb_ptr + index).dereference())
 
 
+class RustStdVecDequePrinter(object):
+    def __init__(self, val):
+        self.__val = val
+
+    @staticmethod
+    def display_hint():
+        return "array"
+
+    def to_string(self):
+        (tail, head, data_ptr, cap) = \
+            rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
+        return (self.__val.type.get_unqualified_type_name() +
+                ("(len: %i, cap: %i)" % (head - tail, cap)))
+
+    def children(self):
+        (tail, head, data_ptr, cap) = \
+            rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
+        gdb_ptr = data_ptr.get_wrapped_value()
+        for index in xrange(tail, head):
+            yield (str(index), (gdb_ptr + index).dereference())
+
+
 class RustStdStringPrinter(object):
     def __init__(self, val):
         self.__val = val
index ef619527e064a34d2f8f387881619570393cde5d..ca1b7507b5e9b0dcc8062c632dd785883b7ae4c3 100644 (file)
@@ -162,10 +162,7 @@ mod boxed {
 #[cfg(test)]
 mod boxed_test;
 pub mod collections;
-#[cfg(any(
-    all(stage0, target_has_atomic = "ptr"),
-    all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-))]
+#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
 pub mod sync;
 pub mod rc;
 pub mod raw_vec;
index 9792d52dd66d26c658bc5e3fbcb380f0f5022081..7a4eda21a601a61442dd1d4fbf6d68295cb29526 100644 (file)
 
 pub use core::task::*;
 
-#[cfg(any(
-    all(stage0, target_has_atomic = "ptr"),
-    all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-))]
+#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
 pub use self::if_arc::*;
 
-#[cfg(any(
-    all(stage0, target_has_atomic = "ptr"),
-    all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-))]
+#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
 mod if_arc {
     use super::*;
     use core::marker::PhantomData;
@@ -53,10 +47,7 @@ unsafe fn wake_local(arc_self: &Arc<Self>) {
         }
     }
 
-    #[cfg(any(
-        all(stage0, target_has_atomic = "ptr"),
-        all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-    ))]
+    #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
     struct ArcWrapped<T>(PhantomData<T>);
 
     unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
index 5efe1e23309a7d7a84e96796149be522763511c9..cc913dfbb4b01e140abb47403998f7a65c224f3a 100644 (file)
@@ -690,14 +690,20 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> {
     /// [`drain`]: #method.drain
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: usize) {
+        let current_len = self.len;
         unsafe {
+            let mut ptr = self.as_mut_ptr().offset(self.len as isize);
+            // Set the final length at the end, keeping in mind that
+            // dropping an element might panic. Works around a missed
+            // optimization, as seen in the following issue:
+            // https://github.com/rust-lang/rust/issues/51802
+            let mut local_len = SetLenOnDrop::new(&mut self.len);
+
             // drop any extra elements
-            while len < self.len {
-                // decrement len before the drop_in_place(), so a panic on Drop
-                // doesn't re-drop the just-failed value.
-                self.len -= 1;
-                let len = self.len;
-                ptr::drop_in_place(self.get_unchecked_mut(len));
+            for _ in len..current_len {
+                local_len.decrement_len(1);
+                ptr = ptr.offset(-1);
+                ptr::drop_in_place(ptr);
             }
         }
     }
@@ -1512,6 +1518,11 @@ fn new(len: &'a mut usize) -> Self {
     fn increment_len(&mut self, increment: usize) {
         self.local_len += increment;
     }
+
+    #[inline]
+    fn decrement_len(&mut self, decrement: usize) {
+        self.local_len -= decrement;
+    }
 }
 
 impl<'a> Drop for SetLenOnDrop<'a> {
index 0aa46dc6d205fa0976caf5a7bbd005abcd4b26e7..fbda425a70bf5d6388455a4a0014e58a0a13d1d0 100644 (file)
@@ -105,11 +105,10 @@ fn main() {
         cmd.arg("--with-jemalloc-prefix=je_");
     }
 
-    // FIXME: building with jemalloc assertions is currently broken.
-    // See <https://github.com/rust-lang/rust/issues/44152>.
-    //if cfg!(feature = "debug") {
-    //    cmd.arg("--enable-debug");
-    //}
+    if cfg!(feature = "debug") {
+        // Enable jemalloc assertions.
+        cmd.arg("--enable-debug");
+    }
 
     cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
     cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
index 64348e05de7db16967708aded5d286e613cd75b1..8e30b0d5d5a17c23371e0945fbaf3872754afa27 100644 (file)
@@ -174,7 +174,10 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
         }
     }
 
-    #[cfg(any(target_os = "android", target_os = "redox", target_os = "solaris"))]
+    #[cfg(any(target_os = "android",
+              target_os = "hermit",
+              target_os = "redox",
+              target_os = "solaris"))]
     #[inline]
     unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
         // On android we currently target API level 9 which unfortunately
@@ -197,7 +200,10 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
         libc::memalign(layout.align(), layout.size()) as *mut u8
     }
 
-    #[cfg(not(any(target_os = "android", target_os = "redox", target_os = "solaris")))]
+    #[cfg(not(any(target_os = "android",
+                  target_os = "hermit",
+                  target_os = "redox",
+                  target_os = "solaris")))]
     #[inline]
     unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
         let mut out = ptr::null_mut();
index 52a6a4d7087d14a35d44a11c39c77fa79d71378d..d549d85b1735dc5066b2973f8549557a813bb9c8 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 52a6a4d7087d14a35d44a11c39c77fa79d71378d
+Subproject commit d549d85b1735dc5066b2973f8549557a813bb9c8
index b6ac248b79f8666331ab77c82d7aa9d311b188ff..39ec5d6411c16c26b3161414426cc6722f18e809 100644 (file)
 use ptr::{self, NonNull};
 use num::NonZeroUsize;
 
-#[unstable(feature = "alloc_internals", issue = "0")]
-#[cfg(stage0)]
-pub type Opaque = u8;
-
 /// Represents the combination of a starting address and
 /// a total capacity of the returned block.
 #[unstable(feature = "allocator_api", issue = "32838")]
@@ -48,7 +44,7 @@ fn size_align<T>() -> (usize, usize) {
 /// use specific allocators with looser requirements.)
 #[stable(feature = "alloc_layout", since = "1.28.0")]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-#[cfg_attr(not(stage0), lang = "alloc_layout")]
+#[lang = "alloc_layout"]
 pub struct Layout {
     // size of the requested block of memory, measured in bytes.
     size_: usize,
index 137e9fe2c1533e251a09e54c6c0a86879c7d4332..009aba5f59869d0c01500a5f485fc633028c73e4 100644 (file)
@@ -1258,7 +1258,7 @@ pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
         let RefMut { value, borrow } = orig;
         RefMut {
             value: f(value),
-            borrow: borrow,
+            borrow,
         }
     }
 
@@ -1324,7 +1324,7 @@ fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
         match borrow.get() {
             UNUSED => {
                 borrow.set(UNUSED - 1);
-                Some(BorrowRefMut { borrow: borrow })
+                Some(BorrowRefMut { borrow })
             },
             _ => None,
         }
@@ -1467,7 +1467,7 @@ impl<T> UnsafeCell<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub const fn new(value: T) -> UnsafeCell<T> {
-        UnsafeCell { value: value }
+        UnsafeCell { value }
     }
 
     /// Unwraps the value.
index 0b8dce19dffa1c053437ce55f3da3cd36760a027..cc52f048b891b578f258dd47bf2f4b03de2d5f93 100644 (file)
 //! UTF-8 and UTF-16 decoding iterators
 
 use fmt;
-use iter::FusedIterator;
 use super::from_u32_unchecked;
 
-/// An iterator over an iterator of bytes of the characters the bytes represent
-/// as UTF-8
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[derive(Clone, Debug)]
-#[allow(deprecated)]
-pub struct DecodeUtf8<I: Iterator<Item = u8>>(::iter::Peekable<I>);
-
-/// Decodes an `Iterator` of bytes as UTF-8.
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[allow(deprecated)]
-#[inline]
-pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> {
-    DecodeUtf8(i.into_iter().peekable())
-}
-
-/// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence.
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[derive(PartialEq, Eq, Debug)]
-#[allow(deprecated)]
-pub struct InvalidSequence(());
-
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[allow(deprecated)]
-impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
-    type Item = Result<char, InvalidSequence>;
-    #[inline]
-
-    fn next(&mut self) -> Option<Result<char, InvalidSequence>> {
-        self.0.next().map(|first_byte| {
-            // Emit InvalidSequence according to
-            // Unicode §5.22 Best Practice for U+FFFD Substitution
-            // http://www.unicode.org/versions/Unicode9.0.0/ch05.pdf#G40630
-
-            // Roughly: consume at least one byte,
-            // then validate one byte at a time and stop before the first unexpected byte
-            // (which might be the valid start of the next byte sequence).
-
-            let mut code_point;
-            macro_rules! first_byte {
-                ($mask: expr) => {
-                    code_point = u32::from(first_byte & $mask)
-                }
-            }
-            macro_rules! continuation_byte {
-                () => { continuation_byte!(0x80..=0xBF) };
-                ($range: pat) => {
-                    match self.0.peek() {
-                        Some(&byte @ $range) => {
-                            code_point = (code_point << 6) | u32::from(byte & 0b0011_1111);
-                            self.0.next();
-                        }
-                        _ => return Err(InvalidSequence(()))
-                    }
-                }
-            }
-
-            match first_byte {
-                0x00..=0x7F => {
-                    first_byte!(0b1111_1111);
-                }
-                0xC2..=0xDF => {
-                    first_byte!(0b0001_1111);
-                    continuation_byte!();
-                }
-                0xE0 => {
-                    first_byte!(0b0000_1111);
-                    continuation_byte!(0xA0..=0xBF);  // 0x80..=0x9F here are overlong
-                    continuation_byte!();
-                }
-                0xE1..=0xEC | 0xEE..=0xEF => {
-                    first_byte!(0b0000_1111);
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                0xED => {
-                    first_byte!(0b0000_1111);
-                    continuation_byte!(0x80..=0x9F);  // 0xA0..0xBF here are surrogates
-                    continuation_byte!();
-                }
-                0xF0 => {
-                    first_byte!(0b0000_0111);
-                    continuation_byte!(0x90..=0xBF);  // 0x80..0x8F here are overlong
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                0xF1..=0xF3 => {
-                    first_byte!(0b0000_0111);
-                    continuation_byte!();
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                0xF4 => {
-                    first_byte!(0b0000_0111);
-                    continuation_byte!(0x80..=0x8F);  // 0x90..0xBF here are beyond char::MAX
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                _ => return Err(InvalidSequence(()))  // Illegal first byte, overlong, or beyond MAX
-            }
-            unsafe {
-                Ok(from_u32_unchecked(code_point))
-            }
-        })
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (lower, upper) = self.0.size_hint();
-
-        // A code point is at most 4 bytes long.
-        let min_code_points = lower / 4;
-
-        (min_code_points, upper)
-    }
-}
-
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[allow(deprecated)]
-impl<I: FusedIterator<Item = u8>> FusedIterator for DecodeUtf8<I> {}
-
 /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
 #[stable(feature = "decode_utf16", since = "1.9.0")]
 #[derive(Clone, Debug)]
index eee78de903628cee1514f40a0dc86315637dc210..33fd6947c1e4b6471d978a13bd69058695cf33e6 100644 (file)
@@ -673,11 +673,11 @@ pub fn is_whitespace(self) -> bool {
     /// assert!('٣'.is_alphanumeric());
     /// assert!('7'.is_alphanumeric());
     /// assert!('৬'.is_alphanumeric());
+    /// assert!('¾'.is_alphanumeric());
+    /// assert!('①'.is_alphanumeric());
     /// assert!('K'.is_alphanumeric());
     /// assert!('و'.is_alphanumeric());
     /// assert!('藏'.is_alphanumeric());
-    /// assert!(!'¾'.is_alphanumeric());
-    /// assert!(!'①'.is_alphanumeric());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -727,11 +727,11 @@ pub(crate) fn is_grapheme_extended(self) -> bool {
     /// assert!('٣'.is_numeric());
     /// assert!('7'.is_numeric());
     /// assert!('৬'.is_numeric());
+    /// assert!('¾'.is_numeric());
+    /// assert!('①'.is_numeric());
     /// assert!(!'K'.is_numeric());
     /// assert!(!'و'.is_numeric());
     /// assert!(!'藏'.is_numeric());
-    /// assert!(!'¾'.is_numeric());
-    /// assert!(!'①'.is_numeric());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
index 59bcf1383f47a27580a05cd6c9fa8f4bd15f0c84..5be673db3200d8b3696749443520c48bafeb964b 100644 (file)
 pub use unicode::tables::UNICODE_VERSION;
 #[unstable(feature = "unicode_version", issue = "49726")]
 pub use unicode::version::UnicodeVersion;
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[allow(deprecated)]
-pub use self::decode::{decode_utf8, DecodeUtf8, InvalidSequence};
 
 use fmt::{self, Write};
 use iter::FusedIterator;
index 98c504a3f7bef380a6ca28cb044bc3c1c0bbf546..6045fac2b4b3d7fe096152772e6d6993d1383083 100644 (file)
@@ -36,6 +36,8 @@ pub struct LocalFutureObj<'a, T> {
     _marker: PhantomData<&'a ()>,
 }
 
+impl<'a, T> Unpin for LocalFutureObj<'a, T> {}
+
 impl<'a, T> LocalFutureObj<'a, T> {
     /// Create a `LocalFutureObj` from a custom trait object representation.
     #[inline]
@@ -104,6 +106,7 @@ fn drop(&mut self) {
 ///   information #44874)
 pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);
 
+impl<'a, T> Unpin for FutureObj<'a, T> {}
 unsafe impl<'a, T> Send for FutureObj<'a, T> {}
 
 impl<'a, T> FutureObj<'a, T> {
index 854cb5f4e3b3f77a1791896e3f8df6d0eaba57dd..9ddf902349dd2e633ae87aa2c03ebebb0e28e96f 100644 (file)
@@ -1087,11 +1087,9 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
 
     /// Perform a volatile load from the `src` pointer
     /// The pointer is not required to be aligned.
-    #[cfg(not(stage0))]
     pub fn unaligned_volatile_load<T>(src: *const T) -> T;
     /// Perform a volatile store to the `dst` pointer.
     /// The pointer is not required to be aligned.
-    #[cfg(not(stage0))]
     pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
 
     /// Returns the square root of an `f32`
index 48c6eb94144296ec7c4785171ec7223337b638b7..5681cfb04f2088c1fece1a7ede7c9d835b3eb0b5 100644 (file)
@@ -507,7 +507,7 @@ fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> where
     fn map<B, F>(self, f: F) -> Map<Self, F> where
         Self: Sized, F: FnMut(Self::Item) -> B,
     {
-        Map{iter: self, f: f}
+        Map { iter: self, f }
     }
 
     /// Calls a closure on each element of an iterator.
@@ -618,7 +618,7 @@ fn for_each<F>(self, mut f: F) where
     fn filter<P>(self, predicate: P) -> Filter<Self, P> where
         Self: Sized, P: FnMut(&Self::Item) -> bool,
     {
-        Filter{iter: self, predicate: predicate}
+        Filter {iter: self, predicate }
     }
 
     /// Creates an iterator that both filters and maps.
@@ -675,7 +675,7 @@ fn filter<P>(self, predicate: P) -> Filter<Self, P> where
     fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where
         Self: Sized, F: FnMut(Self::Item) -> Option<B>,
     {
-        FilterMap { iter: self, f: f }
+        FilterMap { iter: self, f }
     }
 
     /// Creates an iterator which gives the current iteration count as well as
@@ -828,7 +828,7 @@ fn peekable(self) -> Peekable<Self> where Self: Sized {
     fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where
         Self: Sized, P: FnMut(&Self::Item) -> bool,
     {
-        SkipWhile{iter: self, flag: false, predicate: predicate}
+        SkipWhile { iter: self, flag: false, predicate }
     }
 
     /// Creates an iterator that yields elements based on a predicate.
@@ -908,7 +908,7 @@ fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where
     fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where
         Self: Sized, P: FnMut(&Self::Item) -> bool,
     {
-        TakeWhile{iter: self, flag: false, predicate: predicate}
+        TakeWhile { iter: self, flag: false, predicate }
     }
 
     /// Creates an iterator that skips the first `n` elements.
@@ -930,7 +930,7 @@ fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn skip(self, n: usize) -> Skip<Self> where Self: Sized {
-        Skip{iter: self, n: n}
+        Skip { iter: self, n }
     }
 
     /// Creates an iterator that yields its first `n` elements.
@@ -962,7 +962,7 @@ fn skip(self, n: usize) -> Skip<Self> where Self: Sized {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn take(self, n: usize) -> Take<Self> where Self: Sized, {
-        Take{iter: self, n: n}
+        Take { iter: self, n }
     }
 
     /// An iterator adaptor similar to [`fold`] that holds internal state and
@@ -1007,7 +1007,7 @@ fn take(self, n: usize) -> Take<Self> where Self: Sized, {
     fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
         where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>,
     {
-        Scan{iter: self, f: f, state: initial_state}
+        Scan { iter: self, f, state: initial_state }
     }
 
     /// Creates an iterator that works like map, but flattens nested structure.
@@ -1256,7 +1256,7 @@ fn fuse(self) -> Fuse<Self> where Self: Sized {
     fn inspect<F>(self, f: F) -> Inspect<Self, F> where
         Self: Sized, F: FnMut(&Self::Item),
     {
-        Inspect{iter: self, f: f}
+        Inspect { iter: self, f }
     }
 
     /// Borrows an iterator, rather than consuming it.
diff --git a/src/libcore/manually_drop_stage0.rs b/src/libcore/manually_drop_stage0.rs
deleted file mode 100644 (file)
index 8643219..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
-///
-/// This wrapper is 0-cost.
-///
-/// # 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<Peach>,
-///     melon: Melon, // Field that’s independent of the other two.
-///     banana: ManuallyDrop<Banana>,
-/// }
-///
-/// 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`.
-///     }
-/// }
-/// ```
-#[stable(feature = "manually_drop", since = "1.20.0")]
-#[allow(unions_with_drop_fields)]
-#[derive(Copy)]
-pub union ManuallyDrop<T>{ value: T }
-
-impl<T> ManuallyDrop<T> {
-    /// 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")]
-    #[rustc_const_unstable(feature = "const_manually_drop_new")]
-    #[inline]
-    pub const fn new(value: T) -> ManuallyDrop<T> {
-        ManuallyDrop { value: value }
-    }
-
-    /// Extract the value from the ManuallyDrop container.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::mem::ManuallyDrop;
-    /// let x = ManuallyDrop::new(Box::new(()));
-    /// let _: Box<()> = ManuallyDrop::into_inner(x);
-    /// ```
-    #[stable(feature = "manually_drop", since = "1.20.0")]
-    #[inline]
-    pub fn into_inner(slot: ManuallyDrop<T>) -> T {
-        unsafe {
-            slot.value
-        }
-    }
-
-    /// Manually drops the contained value.
-    ///
-    /// # 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.
-    #[stable(feature = "manually_drop", since = "1.20.0")]
-    #[inline]
-    pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
-        ptr::drop_in_place(&mut slot.value)
-    }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T> Deref for ManuallyDrop<T> {
-    type Target = T;
-    #[inline]
-    fn deref(&self) -> &Self::Target {
-        unsafe {
-            &self.value
-        }
-    }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T> DerefMut for ManuallyDrop<T> {
-    #[inline]
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        unsafe {
-            &mut self.value
-        }
-    }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
-    fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
-        unsafe {
-            fmt.debug_tuple("ManuallyDrop").field(&self.value).finish()
-        }
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Clone> Clone for ManuallyDrop<T> {
-    fn clone(&self) -> Self {
-        ManuallyDrop::new(self.deref().clone())
-    }
-
-    fn clone_from(&mut self, source: &Self) {
-        self.deref_mut().clone_from(source);
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Default> Default for ManuallyDrop<T> {
-    fn default() -> Self {
-        ManuallyDrop::new(Default::default())
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: PartialEq> PartialEq for ManuallyDrop<T> {
-    fn eq(&self, other: &Self) -> bool {
-        self.deref().eq(other)
-    }
-
-    fn ne(&self, other: &Self) -> bool {
-        self.deref().ne(other)
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Eq> Eq for ManuallyDrop<T> {}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: PartialOrd> PartialOrd for ManuallyDrop<T> {
-    fn partial_cmp(&self, other: &Self) -> Option<::cmp::Ordering> {
-        self.deref().partial_cmp(other)
-    }
-
-    fn lt(&self, other: &Self) -> bool {
-        self.deref().lt(other)
-    }
-
-    fn le(&self, other: &Self) -> bool {
-        self.deref().le(other)
-    }
-
-    fn gt(&self, other: &Self) -> bool {
-        self.deref().gt(other)
-    }
-
-    fn ge(&self, other: &Self) -> bool {
-        self.deref().ge(other)
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Ord> Ord for ManuallyDrop<T> {
-    fn cmp(&self, other: &Self) -> ::cmp::Ordering {
-        self.deref().cmp(other)
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> {
-    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
-        self.deref().hash(state);
-    }
-}
index 1a54f03bb00673ed2c2a431e7e76ef2a3ffd333f..8a74e7c6f1cc66d628432457eee60f26acb62fa8 100644 (file)
@@ -953,7 +953,6 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
 ///     }
 /// }
 /// ```
-#[cfg(not(stage0))]
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -961,10 +960,6 @@ pub struct ManuallyDrop<T> {
     value: T,
 }
 
-#[cfg(stage0)]
-include!("manually_drop_stage0.rs");
-
-#[cfg(not(stage0))]
 impl<T> ManuallyDrop<T> {
     /// Wrap a value to be manually dropped.
     ///
@@ -1010,7 +1005,6 @@ pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
     }
 }
 
-#[cfg(not(stage0))]
 #[stable(feature = "manually_drop", since = "1.20.0")]
 impl<T> Deref for ManuallyDrop<T> {
     type Target = T;
@@ -1020,7 +1014,6 @@ fn deref(&self) -> &Self::Target {
     }
 }
 
-#[cfg(not(stage0))]
 #[stable(feature = "manually_drop", since = "1.20.0")]
 impl<T> DerefMut for ManuallyDrop<T> {
     #[inline]
index 69418434ebead36b0ed701744ab61c4ce7d25dfa..e7ed94d4d91c2a0646dc7545849108bc4ae36582 100644 (file)
@@ -40,7 +40,7 @@ pub struct Decimal<'a> {
 
 impl<'a> Decimal<'a> {
     pub fn new(integral: &'a [u8], fractional: &'a [u8], exp: i64) -> Decimal<'a> {
-        Decimal { integral: integral, fractional: fractional, exp: exp }
+        Decimal { integral, fractional, exp }
     }
 }
 
index 456d0e956d42aad36258acb069674438e5845f4e..38f4e4687a99b6358b946eb7ced49fd7796bcb2e 100644 (file)
@@ -45,7 +45,7 @@ pub struct Unpacked {
 
 impl Unpacked {
     pub fn new(sig: u64, k: i16) -> Self {
-        Unpacked { sig: sig, k: k }
+        Unpacked { sig, k }
     }
 }
 
@@ -317,13 +317,13 @@ pub fn big_to_fp(f: &Big) -> Fp {
     // We cut off all bits prior to the index `start`, i.e., we effectively right-shift by
     // an amount of `start`, so this is also the exponent we need.
     let e = start as i16;
-    let rounded_down = Fp { f: leading, e: e }.normalize();
+    let rounded_down = Fp { f: leading, e }.normalize();
     // Round (half-to-even) depending on the truncated bits.
     match num::compare_with_half_ulp(f, start) {
         Less => rounded_down,
         Equal if leading % 2 == 0 => rounded_down,
         Equal | Greater => match leading.checked_add(1) {
-            Some(f) => Fp { f: f, e: e }.normalize(),
+            Some(f) => Fp { f, e }.normalize(),
             None => Fp { f: 1 << 63, e: e + 1 },
         }
     }
index 97bcba2f2ffbc8b9da881fe3bdcdb789b5c3ee8e..b0561da5934c0be5fa06e8dd0b9ec7da27ab04da 100644 (file)
@@ -42,7 +42,7 @@ pub fn mul(&self, other: &Fp) -> Fp {
         let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */;
         let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
         let e = self.e + other.e + 64;
-        Fp { f: f, e: e }
+        Fp { f, e }
     }
 
     /// Normalizes itself so that the resulting mantissa is at least `2^63`.
@@ -74,7 +74,7 @@ pub fn normalize(&self) -> Fp {
             e -= 1;
         }
         debug_assert!(f >= (1 >> 63));
-        Fp { f: f, e: e }
+        Fp { f, e }
     }
 
     /// Normalizes itself to have the shared exponent.
index b779eefce5752c1bf100488f35106454c83c7770..c34a56f288fd44c3555f6dabf3fe18e99a641306 100644 (file)
@@ -77,8 +77,8 @@ pub fn decode<T: DecodableFloat>(v: T) -> (/*negative?*/ bool, FullDecoded) {
             // neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp)
             // Float::integer_decode always preserves the exponent,
             // so the mantissa is scaled for subnormals.
-            FullDecoded::Finite(Decoded { mant: mant, minus: 1, plus: 1,
-                                          exp: exp, inclusive: even })
+            FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1,
+                                          exp, inclusive: even })
         }
         FpCategory::Normal => {
             let minnorm = <T as DecodableFloat>::min_pos_norm_value().integer_decode();
index beaa6e140a6993b978c6b60bf63f7eb775bb2199..21a2e72dac8c37f7411b18841087689a37bc1b24 100644 (file)
@@ -424,20 +424,20 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
     match full_decoded {
         FullDecoded::Nan => {
             parts[0] = Part::Copy(b"NaN");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Infinite => {
             parts[0] = Part::Copy(b"inf");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Zero => {
             if frac_digits > 0 { // [0.][0000]
                 parts[0] = Part::Copy(b"0.");
                 parts[1] = Part::Zero(frac_digits);
-                Formatted { sign: sign, parts: &parts[..2] }
+                Formatted { sign, parts: &parts[..2] }
             } else {
                 parts[0] = Part::Copy(b"0");
-                Formatted { sign: sign, parts: &parts[..1] }
+                Formatted { sign, parts: &parts[..1] }
             }
         }
         FullDecoded::Finite(ref decoded) => {
@@ -480,11 +480,11 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
     match full_decoded {
         FullDecoded::Nan => {
             parts[0] = Part::Copy(b"NaN");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Infinite => {
             parts[0] = Part::Copy(b"inf");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Zero => {
             parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 {
@@ -492,7 +492,7 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
             } else {
                 Part::Copy(if upper { b"0E0" } else { b"0e0" })
             };
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Finite(ref decoded) => {
             let (len, exp) = format_shortest(decoded, buf);
@@ -502,7 +502,7 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
             } else {
                 digits_to_exp_str(&buf[..len], exp, 0, upper, parts)
             };
-            Formatted { sign: sign, parts: parts }
+            Formatted { sign, parts }
         }
     }
 }
@@ -558,21 +558,21 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
     match full_decoded {
         FullDecoded::Nan => {
             parts[0] = Part::Copy(b"NaN");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Infinite => {
             parts[0] = Part::Copy(b"inf");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Zero => {
             if ndigits > 1 { // [0.][0000][e0]
                 parts[0] = Part::Copy(b"0.");
                 parts[1] = Part::Zero(ndigits - 1);
                 parts[2] = Part::Copy(if upper { b"E0" } else { b"e0" });
-                Formatted { sign: sign, parts: &parts[..3] }
+                Formatted { sign, parts: &parts[..3] }
             } else {
                 parts[0] = Part::Copy(if upper { b"0E0" } else { b"0e0" });
-                Formatted { sign: sign, parts: &parts[..1] }
+                Formatted { sign, parts: &parts[..1] }
             }
         }
         FullDecoded::Finite(ref decoded) => {
@@ -613,20 +613,20 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
     match full_decoded {
         FullDecoded::Nan => {
             parts[0] = Part::Copy(b"NaN");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Infinite => {
             parts[0] = Part::Copy(b"inf");
-            Formatted { sign: sign, parts: &parts[..1] }
+            Formatted { sign, parts: &parts[..1] }
         }
         FullDecoded::Zero => {
             if frac_digits > 0 { // [0.][0000]
                 parts[0] = Part::Copy(b"0.");
                 parts[1] = Part::Zero(frac_digits);
-                Formatted { sign: sign, parts: &parts[..2] }
+                Formatted { sign, parts: &parts[..2] }
             } else {
                 parts[0] = Part::Copy(b"0");
-                Formatted { sign: sign, parts: &parts[..1] }
+                Formatted { sign, parts: &parts[..1] }
             }
         }
         FullDecoded::Finite(ref decoded) => {
@@ -646,10 +646,10 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
                 if frac_digits > 0 { // [0.][0000]
                     parts[0] = Part::Copy(b"0.");
                     parts[1] = Part::Zero(frac_digits);
-                    Formatted { sign: sign, parts: &parts[..2] }
+                    Formatted { sign, parts: &parts[..2] }
                 } else {
                     parts[0] = Part::Copy(b"0");
-                    Formatted { sign: sign, parts: &parts[..1] }
+                    Formatted { sign, parts: &parts[..1] }
                 }
             } else {
                 Formatted { sign,
index f33186e59c2e6a65107aee8c436c8f852ab44e67..effe073c3816c4936eabadc58944a62679c34f7f 100644 (file)
@@ -129,7 +129,7 @@ pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) {
     let idx = ((gamma as i32) - offset) * range / domain;
     let (f, e, k) = CACHED_POW10[idx as usize];
     debug_assert!(alpha <= e && e <= gamma);
-    (k, Fp { f: f, e: e })
+    (k, Fp { f, e })
 }
 
 /// Given `x > 0`, returns `(k, 10^k)` such that `10^k <= x < 10^(k+1)`.
index 3bc2861460e1455024c9e1dc06c58d3b8c2de2a7..6e2fbf6f84f0f48a63832f877f69d78256362187 100644 (file)
@@ -1892,47 +1892,119 @@ pub fn is_positive(self) -> bool { self > 0 }
             pub fn is_negative(self) -> bool { self < 0 }
         }
 
-        /// Return the memory representation of this integer as a byte array.
+        /// Return the memory representation of this integer as a byte array in
+        /// big-endian (network) byte order.
         ///
-        /// The target platform’s native endianness is used.
-        /// Portable code likely wants to use this after [`to_be`] or [`to_le`].
+        /// # Examples
         ///
-        /// [`to_be`]: #method.to_be
-        /// [`to_le`]: #method.to_le
+        /// ```
+        /// #![feature(int_to_from_bytes)]
+        ///
+        /// let bytes = 0x12345678i32.to_be_bytes();
+        /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_be().to_ne_bytes()
+        }
+
+        /// Return the memory representation of this integer as a byte array in
+        /// little-endian byte order.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_to_from_bytes)]
+        ///
+        /// let bytes = 0x12345678i32.to_le_bytes();
+        /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_le().to_ne_bytes()
+        }
+
+        /// Return the memory representation of this integer as a byte array in
+        /// native byte order.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
+        /// instead.
+        ///
+        /// [`to_be_bytes`]: #method.to_be_bytes
+        /// [`to_le_bytes`]: #method.to_le_bytes
         ///
         /// # Examples
         ///
         /// ```
         /// #![feature(int_to_from_bytes)]
         ///
-        /// let bytes = i32::min_value().to_be().to_bytes();
+        /// let bytes = i32::min_value().to_be().to_ne_bytes();
         /// assert_eq!(bytes, [0x80, 0, 0, 0]);
         /// ```
-        #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
         #[inline]
-        pub fn to_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        pub fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
             unsafe { mem::transmute(self) }
         }
 
-        /// Create an integer value from its memory representation as a byte array.
+        /// Create an integer value from its representation as a byte array in
+        /// big endian.
         ///
-        /// The target platform’s native endianness is used.
-        /// Portable code likely wants to use [`from_be`] or [`from_le`] after this.
+        /// # Examples
         ///
-        /// [`from_be`]: #method.from_be
-        /// [`from_le`]: #method.from_le
+        /// ```
+        /// #![feature(int_to_from_bytes)]
+        ///
+        /// let int = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
+        /// assert_eq!(int, 0x12_34_56_78);
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_be(Self::from_ne_bytes(bytes))
+        }
+
+        /// Create an integer value from its representation as a byte array in
+        /// little endian.
         ///
         /// # Examples
         ///
         /// ```
         /// #![feature(int_to_from_bytes)]
         ///
-        /// let int = i32::from_be(i32::from_bytes([0x80, 0, 0, 0]));
+        /// let int = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
+        /// assert_eq!(int, 0x78_56_34_12);
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_le(Self::from_ne_bytes(bytes))
+        }
+
+        /// Create an integer value from its memory representation as a byte
+        /// array in native endianness.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
+        /// appropriate instead.
+        ///
+        /// [`from_be_bytes`]: #method.from_be_bytes
+        /// [`from_le_bytes`]: #method.from_le_bytes
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_to_from_bytes)]
+        ///
+        /// let int = i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]));
         /// assert_eq!(int, i32::min_value());
         /// ```
-        #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
         #[inline]
-        pub fn from_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        pub fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             unsafe { mem::transmute(bytes) }
         }
     }
@@ -3517,7 +3589,7 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// let bytes = 0x1234_5678_u32.to_be().to_bytes();
         /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
         /// ```
-        #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
         #[inline]
         pub fn to_bytes(self) -> [u8; mem::size_of::<Self>()] {
             unsafe { mem::transmute(self) }
@@ -3539,7 +3611,7 @@ pub fn wrapping_next_power_of_two(self) -> Self {
         /// let int = u32::from_be(u32::from_bytes([0x12, 0x34, 0x56, 0x78]));
         /// assert_eq!(int, 0x1234_5678_u32);
         /// ```
-        #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
         #[inline]
         pub fn from_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             unsafe { mem::transmute(bytes) }
index cd896859b16bc7eb703de393279305f37d8529b5..da72f3748425d9f1e77b54c837dddf9a339b9a28 100644 (file)
@@ -13,7 +13,7 @@
 /// Trait that indicates that this is a pointer or a wrapper for one,
 /// where unsizing can be performed on the pointee.
 ///
-/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce]
+/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce]
 /// for more details.
 ///
 /// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize<U>`
index fe5914c72e1ac27c3760e64c26b6ec4824e4524b..c8670e5ec34d347b9f2f5aef6180ee29f10a0b4f 100644 (file)
@@ -448,6 +448,12 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 /// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use
 /// because it will attempt to drop the value previously at `*src`.
 ///
+/// Just like in C, whether an operation is volatile has no bearing whatsoever
+/// on questions involving concurrent access from multiple threads. Volatile
+/// accesses behave exactly like non-atomic accesses in that regard. In particular,
+/// a race between a `read_volatile` and any write operation to the same location
+/// is undefined behavior.
+///
 /// # Examples
 ///
 /// Basic usage:
@@ -498,6 +504,12 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 /// This is appropriate for initializing uninitialized memory, or overwriting
 /// memory that has previously been `read` from.
 ///
+/// Just like in C, whether an operation is volatile has no bearing whatsoever
+/// on questions involving concurrent access from multiple threads. Volatile
+/// accesses behave exactly like non-atomic accesses in that regard. In particular,
+/// a race between a `write_volatile` and any other operation (reading or writing)
+/// on the same location is undefined behavior.
+///
 /// # Examples
 ///
 /// Basic usage:
@@ -680,46 +692,6 @@ pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
         }
     }
 
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// If the address different between the two pointers ia not a multiple of
-    /// `mem::size_of::<T>()` then the result of the division is rounded towards
-    /// zero.
-    ///
-    /// This function returns `None` if `T` is a zero-sized type.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(offset_to)]
-    /// #![allow(deprecated)]
-    ///
-    /// fn main() {
-    ///     let a = [0; 5];
-    ///     let ptr1: *const i32 = &a[1];
-    ///     let ptr2: *const i32 = &a[3];
-    ///     assert_eq!(ptr1.offset_to(ptr2), Some(2));
-    ///     assert_eq!(ptr2.offset_to(ptr1), Some(-2));
-    ///     assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
-    ///     assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
-    /// }
-    /// ```
-    #[unstable(feature = "offset_to", issue = "41079")]
-    #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \
-        opposite argument order.  If you're writing unsafe code, consider `offset_from`.")]
-    #[inline]
-    pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
-        let size = mem::size_of::<T>();
-        if size == 0 {
-            None
-        } else {
-            Some(other.wrapping_offset_from(self))
-        }
-    }
-
     /// Calculates the distance between two pointers. The returned value is in
     /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
     ///
@@ -1097,6 +1069,12 @@ pub unsafe fn read(self) -> T
     /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
     /// because it will attempt to drop the value previously at `*self`.
     ///
+    /// Just like in C, whether an operation is volatile has no bearing whatsoever
+    /// on questions involving concurrent access from multiple threads. Volatile
+    /// accesses behave exactly like non-atomic accesses in that regard. In particular,
+    /// a race between a `read_volatile` and any write operation to the same location
+    /// is undefined behavior.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1464,46 +1442,6 @@ pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
         }
     }
 
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// If the address different between the two pointers ia not a multiple of
-    /// `mem::size_of::<T>()` then the result of the division is rounded towards
-    /// zero.
-    ///
-    /// This function returns `None` if `T` is a zero-sized type.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(offset_to)]
-    /// #![allow(deprecated)]
-    ///
-    /// fn main() {
-    ///     let mut a = [0; 5];
-    ///     let ptr1: *mut i32 = &mut a[1];
-    ///     let ptr2: *mut i32 = &mut a[3];
-    ///     assert_eq!(ptr1.offset_to(ptr2), Some(2));
-    ///     assert_eq!(ptr2.offset_to(ptr1), Some(-2));
-    ///     assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
-    ///     assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
-    /// }
-    /// ```
-    #[unstable(feature = "offset_to", issue = "41079")]
-    #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \
-        opposite argument order.  If you're writing unsafe code, consider `offset_from`.")]
-    #[inline]
-    pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
-        let size = mem::size_of::<T>();
-        if size == 0 {
-            None
-        } else {
-            Some(other.wrapping_offset_from(self))
-        }
-    }
-
     /// Calculates the distance between two pointers. The returned value is in
     /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
     ///
@@ -1870,6 +1808,12 @@ pub unsafe fn read(self) -> T
     /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
     /// because it will attempt to drop the value previously at `*self`.
     ///
+    /// Just like in C, whether an operation is volatile has no bearing whatsoever
+    /// on questions involving concurrent access from multiple threads. Volatile
+    /// accesses behave exactly like non-atomic accesses in that regard. In particular,
+    /// a race between a `read_volatile` and any write operation to the same location
+    /// is undefined behavior.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -2185,6 +2129,12 @@ pub unsafe fn write_bytes(self, val: u8, count: usize)
     /// This is appropriate for initializing uninitialized memory, or overwriting
     /// memory that has previously been `read` from.
     ///
+    /// Just like in C, whether an operation is volatile has no bearing whatsoever
+    /// on questions involving concurrent access from multiple threads. Volatile
+    /// accesses behave exactly like non-atomic accesses in that regard. In particular,
+    /// a race between a `write_volatile` and any other operation (reading or writing)
+    /// on the same location is undefined behavior.
+    ///
     /// # Examples
     ///
     /// Basic usage:
index 72e7b57a6cb3cee63e87b970f026d946e9c40ee8..c9d3c7fea9839e1ed3da89ae8b61971ff69c493f 100644 (file)
@@ -100,24 +100,30 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     // - the first remaining bytes, < 2 word size
     let len = text.len();
     let ptr = text.as_ptr();
-    let usize_bytes = mem::size_of::<usize>();
+    type Chunk = usize;
 
-    let mut offset = {
-        // We call this just to obtain the length of the suffix
-        let (_, _, suffix) = unsafe { text.align_to::<usize>() };
-        len - suffix.len()
+    let (min_aligned_offset, max_aligned_offset) = {
+        // We call this just to obtain the length of the prefix and suffix.
+        // In the middle we always process two chunks at once.
+        let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() };
+        (prefix.len(), len - suffix.len())
     };
+
+    let mut offset = max_aligned_offset;
     if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
         return Some(offset + index);
     }
 
-    // search the body of the text
+    // search the body of the text, make sure we don't cross min_aligned_offset.
+    // offset is always aligned, so just testing `>` is sufficient and avoids possible
+    // overflow.
     let repeated_x = repeat_byte(x);
+    let chunk_bytes = mem::size_of::<Chunk>();
 
-    while offset >= 2 * usize_bytes {
+    while offset > min_aligned_offset {
         unsafe {
-            let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
-            let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
+            let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk);
+            let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk);
 
             // break if there is a matching byte
             let zu = contains_zero_byte(u ^ repeated_x);
@@ -126,7 +132,7 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
                 break;
             }
         }
-        offset -= 2 * usize_bytes;
+        offset -= 2 * chunk_bytes;
     }
 
     // find the byte before the point the body loop stopped
index b766140ffe99a1e37f292e729df55ecb4850ad57..dfebe460ff80150eb1f44e1075f723d18e6fb9ce 100644 (file)
@@ -75,44 +75,6 @@ struct FatPtr<T> {
 // Extension traits
 //
 
-// Use macros to be generic over const/mut
-macro_rules! slice_offset {
-    ($ptr:expr, $by:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            (ptr as *mut i8).wrapping_offset($by) as _
-        } else {
-            ptr.offset($by)
-        }
-    }};
-}
-
-// make a &T from a *const T
-macro_rules! make_ref {
-    ($ptr:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            // Use a non-null pointer value
-            &*(1 as *mut _)
-        } else {
-            &*ptr
-        }
-    }};
-}
-
-// make a &mut T from a *mut T
-macro_rules! make_ref_mut {
-    ($ptr:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            // Use a non-null pointer value
-            &mut *(1 as *mut _)
-        } else {
-            &mut *ptr
-        }
-    }};
-}
-
 #[lang = "slice"]
 #[cfg(not(test))]
 impl<T> [T] {
@@ -580,17 +542,18 @@ pub fn reverse(&mut self) {
     #[inline]
     pub fn iter(&self) -> Iter<T> {
         unsafe {
-            let p = if mem::size_of::<T>() == 0 {
-                1 as *const _
+            let ptr = self.as_ptr();
+            assume(!ptr.is_null());
+
+            let end = if mem::size_of::<T>() == 0 {
+                (ptr as *const u8).wrapping_offset(self.len() as isize) as *const T
             } else {
-                let p = self.as_ptr();
-                assume(!p.is_null());
-                p
+                ptr.offset(self.len() as isize)
             };
 
             Iter {
-                ptr: p,
-                end: slice_offset!(p, self.len() as isize),
+                ptr,
+                end,
                 _marker: marker::PhantomData
             }
         }
@@ -611,17 +574,18 @@ pub fn iter(&self) -> Iter<T> {
     #[inline]
     pub fn iter_mut(&mut self) -> IterMut<T> {
         unsafe {
-            let p = if mem::size_of::<T>() == 0 {
-                1 as *mut _
+            let ptr = self.as_mut_ptr();
+            assume(!ptr.is_null());
+
+            let end = if mem::size_of::<T>() == 0 {
+                (ptr as *mut u8).wrapping_offset(self.len() as isize) as *mut T
             } else {
-                let p = self.as_mut_ptr();
-                assume(!p.is_null());
-                p
+                ptr.offset(self.len() as isize)
             };
 
             IterMut {
-                ptr: p,
-                end: slice_offset!(p, self.len() as isize),
+                ptr,
+                end,
                 _marker: marker::PhantomData
             }
         }
@@ -657,7 +621,7 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     #[inline]
     pub fn windows(&self, size: usize) -> Windows<T> {
         assert!(size != 0);
-        Windows { v: self, size: size }
+        Windows { v: self, size }
     }
 
     /// Returns an iterator over `chunk_size` elements of the slice at a
@@ -688,7 +652,7 @@ pub fn windows(&self, size: usize) -> Windows<T> {
     #[inline]
     pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
         assert!(chunk_size != 0);
-        Chunks { v: self, chunk_size: chunk_size }
+        Chunks { v: self, chunk_size }
     }
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
@@ -723,7 +687,7 @@ pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
     #[inline]
     pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
         assert!(chunk_size != 0);
-        ChunksMut { v: self, chunk_size: chunk_size }
+        ChunksMut { v: self, chunk_size }
     }
 
     /// Returns an iterator over `chunk_size` elements of the slice at a
@@ -760,7 +724,7 @@ pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
         let rem = self.len() % chunk_size;
         let len = self.len() - rem;
         let (fst, snd) = self.split_at(len);
-        ExactChunks { v: fst, rem: snd, chunk_size: chunk_size}
+        ExactChunks { v: fst, rem: snd, chunk_size }
     }
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
@@ -802,7 +766,7 @@ pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
         let rem = self.len() % chunk_size;
         let len = self.len() - rem;
         let (fst, snd) = self.split_at_mut(len);
-        ExactChunksMut { v: fst, rem: snd, chunk_size: chunk_size}
+        ExactChunksMut { v: fst, rem: snd, chunk_size }
     }
 
     /// Divides one slice into two at an index.
@@ -952,7 +916,7 @@ pub fn split<F>(&self, pred: F) -> Split<T, F>
     pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
         where F: FnMut(&T) -> bool
     {
-        SplitMut { v: self, pred: pred, finished: false }
+        SplitMut { v: self, pred, finished: false }
     }
 
     /// Returns an iterator over subslices separated by elements that match
@@ -2373,14 +2337,88 @@ fn into_iter(self) -> IterMut<'a, T> {
     }
 }
 
-#[inline]
+// Macro helper functions
+#[inline(always)]
 fn size_from_ptr<T>(_: *const T) -> usize {
     mem::size_of::<T>()
 }
 
+// Inlining is_empty and len makes a huge performance difference
+macro_rules! is_empty {
+    // The way we encode the length of a ZST iterator, this works both for ZST
+    // and non-ZST.
+    ($self: ident) => {$self.ptr == $self.end}
+}
+// To get rid of some bounds checks (see `position`), we compute the length in a somewhat
+// unexpected way. (Tested by `codegen/slice-position-bounds-check`.)
+macro_rules! len {
+    ($self: ident) => {{
+        let start = $self.ptr;
+        let diff = ($self.end as usize).wrapping_sub(start as usize);
+        let size = size_from_ptr(start);
+        if size == 0 {
+            diff
+        } else {
+            // Using division instead of `offset_from` helps LLVM remove bounds checks
+            diff / size
+        }
+    }}
+}
+
 // The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
-    (struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => {
+    (struct $name:ident -> $ptr:ty, $elem:ty, $raw_mut:tt, $( $mut_:tt )*) => {
+        impl<'a, T> $name<'a, T> {
+            // Helper function for creating a slice from the iterator.
+            #[inline(always)]
+            fn make_slice(&self) -> &'a [T] {
+                unsafe { from_raw_parts(self.ptr, len!(self)) }
+            }
+
+            // 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.
+            #[inline(always)]
+            unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T {
+                if mem::size_of::<T>() == 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;
+                    self.ptr
+                } else {
+                    let old = self.ptr;
+                    self.ptr = self.ptr.offset(offset);
+                    old
+                }
+            }
+
+            // 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.
+            #[inline(always)]
+            unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T {
+                if mem::size_of::<T>() == 0 {
+                    self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T;
+                    self.ptr
+                } else {
+                    self.end = self.end.offset(-offset);
+                    self.end
+                }
+            }
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, T> ExactSizeIterator for $name<'a, T> {
+            #[inline(always)]
+            fn len(&self) -> usize {
+                len!(self)
+            }
+
+            #[inline(always)]
+            fn is_empty(&self) -> bool {
+                is_empty!(self)
+            }
+        }
+
         #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, T> Iterator for $name<'a, T> {
             type Item = $elem;
@@ -2389,33 +2427,48 @@ impl<'a, T> Iterator for $name<'a, T> {
             fn next(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
                 unsafe {
+                    assume(!self.ptr.is_null());
                     if mem::size_of::<T>() != 0 {
-                        assume(!self.ptr.is_null());
                         assume(!self.end.is_null());
                     }
-                    if self.ptr == self.end {
+                    if is_empty!(self) {
                         None
                     } else {
-                        Some($mkref!(self.ptr.post_inc()))
+                        Some(& $( $mut_ )* *self.post_inc_start(1))
                     }
                 }
             }
 
             #[inline]
             fn size_hint(&self) -> (usize, Option<usize>) {
-                let exact = unsafe { ptrdistance(self.ptr, self.end) };
+                let exact = len!(self);
                 (exact, Some(exact))
             }
 
             #[inline]
             fn count(self) -> usize {
-                self.len()
+                len!(self)
             }
 
             #[inline]
             fn nth(&mut self, n: usize) -> Option<$elem> {
-                // Call helper method. Can't put the definition here because mut versus const.
-                self.iter_nth(n)
+                if n >= len!(self) {
+                    // This iterator is now empty.
+                    if mem::size_of::<T>() == 0 {
+                        // We have to do it this way as `ptr` may never be 0, but `end`
+                        // could be (due to wrapping).
+                        self.end = self.ptr;
+                    } else {
+                        self.ptr = self.end;
+                    }
+                    return None;
+                }
+                // We are in bounds. `offset` does the right thing even for ZSTs.
+                unsafe {
+                    let elem = Some(& $( $mut_ )* *self.ptr.offset(n as isize));
+                    self.post_inc_start((n as isize).wrapping_add(1));
+                    elem
+                }
             }
 
             #[inline]
@@ -2430,14 +2483,14 @@ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
                 // manual unrolling is needed when there are conditional exits from the loop
                 let mut accum = init;
                 unsafe {
-                    while ptrdistance(self.ptr, self.end) >= 4 {
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
+                    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))?;
                     }
-                    while self.ptr != self.end {
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
+                    while !is_empty!(self) {
+                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
                     }
                 }
                 Try::from_ok(accum)
@@ -2462,9 +2515,8 @@ fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
                 Self: Sized,
                 P: FnMut(Self::Item) -> bool,
             {
-                // The addition might panic on overflow
-                // Use the len of the slice to hint optimizer to remove result index bounds check.
-                let n = make_slice!(self.ptr, self.end).len();
+                // The addition might panic on overflow.
+                let n = len!(self);
                 self.try_fold(0, move |i, x| {
                     if predicate(x) { Err(i) }
                     else { Ok(i + 1) }
@@ -2481,9 +2533,7 @@ fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
                 Self: Sized + ExactSizeIterator + DoubleEndedIterator
             {
                 // No need for an overflow check here, because `ExactSizeIterator`
-                // implies that the number of elements fits into a `usize`.
-                // Use the len of the slice to hint optimizer to remove result index bounds check.
-                let n = make_slice!(self.ptr, self.end).len();
+                let n = len!(self);
                 self.try_rfold(n, move |i, x| {
                     let i = i - 1;
                     if predicate(x) { Err(i) }
@@ -2502,14 +2552,14 @@ impl<'a, T> DoubleEndedIterator for $name<'a, T> {
             fn next_back(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
                 unsafe {
+                    assume(!self.ptr.is_null());
                     if mem::size_of::<T>() != 0 {
-                        assume(!self.ptr.is_null());
                         assume(!self.end.is_null());
                     }
-                    if self.end == self.ptr {
+                    if is_empty!(self) {
                         None
                     } else {
-                        Some($mkref!(self.end.pre_dec()))
+                        Some(& $( $mut_ )* *self.pre_dec_end(1))
                     }
                 }
             }
@@ -2521,14 +2571,15 @@ fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
                 // manual unrolling is needed when there are conditional exits from the loop
                 let mut accum = init;
                 unsafe {
-                    while ptrdistance(self.ptr, self.end) >= 4 {
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
+                    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))?;
                     }
-                    while self.ptr != self.end {
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
+                    // inlining is_empty everywhere makes a huge performance difference
+                    while !is_empty!(self) {
+                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
                     }
                 }
                 Try::from_ok(accum)
@@ -2556,34 +2607,6 @@ unsafe impl<'a, T> TrustedLen for $name<'a, T> {}
     }
 }
 
-macro_rules! make_slice {
-    ($start: expr, $end: expr) => {{
-        let start = $start;
-        let diff = ($end as usize).wrapping_sub(start as usize);
-        if size_from_ptr(start) == 0 {
-            // use a non-null pointer value
-            unsafe { from_raw_parts(1 as *const _, diff) }
-        } else {
-            let len = diff / size_from_ptr(start);
-            unsafe { from_raw_parts(start, len) }
-        }
-    }}
-}
-
-macro_rules! make_mut_slice {
-    ($start: expr, $end: expr) => {{
-        let start = $start;
-        let diff = ($end as usize).wrapping_sub(start as usize);
-        if size_from_ptr(start) == 0 {
-            // use a non-null pointer value
-            unsafe { from_raw_parts_mut(1 as *mut _, diff) }
-        } else {
-            let len = diff / size_from_ptr(start);
-            unsafe { from_raw_parts_mut(start, len) }
-        }
-    }}
-}
-
 /// Immutable slice iterator
 ///
 /// This struct is created by the [`iter`] method on [slices].
@@ -2607,7 +2630,9 @@ macro_rules! make_mut_slice {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     ptr: *const T,
-    end: *const T,
+    end: *const T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
+                   // ptr == end is a quick test for the Iterator being empty, that works
+                   // for both ZST and non-ZST.
     _marker: marker::PhantomData<&'a T>,
 }
 
@@ -2652,32 +2677,11 @@ impl<'a, T> Iter<'a, T> {
     /// ```
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     pub fn as_slice(&self) -> &'a [T] {
-        make_slice!(self.ptr, self.end)
-    }
-
-    // Helper function for Iter::nth
-    fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
-        match self.as_slice().get(n) {
-            Some(elem_ref) => unsafe {
-                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(elem_ref)
-            },
-            None => {
-                self.ptr = self.end;
-                None
-            }
-        }
+        self.make_slice()
     }
 }
 
-iterator!{struct Iter -> *const T, &'a T, make_ref}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Iter<'a, T> {
-    fn is_empty(&self) -> bool {
-        self.ptr == self.end
-    }
-}
+iterator!{struct Iter -> *const T, &'a T, const, /* no mut */}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Clone for Iter<'a, T> {
@@ -2718,7 +2722,9 @@ fn as_ref(&self) -> &[T] {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     ptr: *mut T,
-    end: *mut T,
+    end: *mut T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
+                 // ptr == end is a quick test for the Iterator being empty, that works
+                 // for both ZST and non-ZST.
     _marker: marker::PhantomData<&'a mut T>,
 }
 
@@ -2726,7 +2732,7 @@ pub struct IterMut<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("IterMut")
-            .field(&make_slice!(self.ptr, self.end))
+            .field(&self.make_slice())
             .finish()
     }
 }
@@ -2772,77 +2778,11 @@ impl<'a, T> IterMut<'a, T> {
     /// ```
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     pub fn into_slice(self) -> &'a mut [T] {
-        make_mut_slice!(self.ptr, self.end)
-    }
-
-    // Helper function for IterMut::nth
-    fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
-        match make_mut_slice!(self.ptr, self.end).get_mut(n) {
-            Some(elem_ref) => unsafe {
-                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(elem_ref)
-            },
-            None => {
-                self.ptr = self.end;
-                None
-            }
-        }
-    }
-}
-
-iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
-    fn is_empty(&self) -> bool {
-        self.ptr == self.end
+        unsafe { from_raw_parts_mut(self.ptr, len!(self)) }
     }
 }
 
-// Return the number of elements of `T` from `start` to `end`.
-// Return the arithmetic difference if `T` is zero size.
-#[inline(always)]
-unsafe fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
-    if mem::size_of::<T>() == 0 {
-        (end as usize).wrapping_sub(start as usize)
-    } else {
-        end.offset_from(start) as usize
-    }
-}
-
-// Extension methods for raw pointers, used by the iterators
-trait PointerExt : Copy {
-    unsafe fn slice_offset(self, i: isize) -> Self;
-
-    /// Increments `self` by 1, but returns the old value.
-    #[inline(always)]
-    unsafe fn post_inc(&mut self) -> Self {
-        let current = *self;
-        *self = self.slice_offset(1);
-        current
-    }
-
-    /// Decrements `self` by 1, and returns the new value.
-    #[inline(always)]
-    unsafe fn pre_dec(&mut self) -> Self {
-        *self = self.slice_offset(-1);
-        *self
-    }
-}
-
-impl<T> PointerExt for *const T {
-    #[inline(always)]
-    unsafe fn slice_offset(self, i: isize) -> Self {
-        slice_offset!(self, i)
-    }
-}
-
-impl<T> PointerExt for *mut T {
-    #[inline(always)]
-    unsafe fn slice_offset(self, i: isize) -> Self {
-        slice_offset!(self, i)
-    }
-}
+iterator!{struct IterMut -> *mut T, &'a mut T, mut, mut}
 
 /// An internal abstraction over the splitting iterators, so that
 /// splitn, splitn_mut etc can be implemented once.
@@ -3927,12 +3867,11 @@ fn may_have_side_effect() -> bool { false }
 /// ```
 /// use std::slice;
 ///
-/// // manifest a slice out of thin air!
-/// let ptr = 0x1234 as *const usize;
-/// let amt = 10;
-/// unsafe {
-///     let slice = slice::from_raw_parts(ptr, amt);
-/// }
+/// // manifest a slice for a single element
+/// let x = 42;
+/// let ptr = &x as *const _;
+/// let slice = unsafe { slice::from_raw_parts(ptr, 1) };
+/// assert_eq!(slice[0], 42);
 /// ```
 ///
 /// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling
index 1e2b18bf9b038fc83fa0485474db7aecaca1e232..e98194c17c8851204520a0123b29722f25fba42d 100644 (file)
@@ -373,7 +373,7 @@ pub fn store(&self, val: bool, order: Ordering) {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn swap(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
     }
@@ -404,7 +404,7 @@ pub fn swap(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
         match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
             Ok(x) => x,
@@ -450,7 +450,7 @@ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> boo
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_exchange(&self,
                             current: bool,
                             new: bool,
@@ -542,7 +542,7 @@ pub fn compare_exchange_weak(&self,
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
     }
@@ -574,7 +574,7 @@ pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
         // We can't use atomic_nand here because it can result in a bool with
         // an invalid value. This happens because the atomic operation is done
@@ -617,7 +617,7 @@ pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
     }
@@ -648,7 +648,7 @@ pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
     }
@@ -795,7 +795,7 @@ pub fn store(&self, ptr: *mut T, order: Ordering) {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
         unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
     }
@@ -825,7 +825,7 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
         match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
             Ok(x) => x,
@@ -864,7 +864,7 @@ pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) ->
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_exchange(&self,
                             current: *mut T,
                             new: *mut T,
@@ -1151,7 +1151,7 @@ pub fn store(&self, val: $int_type, order: Ordering) {
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(any(stage0, target_has_atomic = "cas"))]
+                #[cfg(target_has_atomic = "cas")]
                 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_swap(self.v.get(), val, order) }
                 }
@@ -1184,7 +1184,7 @@ pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(any(stage0, target_has_atomic = "cas"))]
+                #[cfg(target_has_atomic = "cas")]
                 pub fn compare_and_swap(&self,
                                         current: $int_type,
                                         new: $int_type,
@@ -1238,7 +1238,7 @@ pub fn compare_and_swap(&self,
 ```"),
                 #[inline]
                 #[$stable_cxchg]
-                #[cfg(any(stage0, target_has_atomic = "cas"))]
+                #[cfg(target_has_atomic = "cas")]
                 pub fn compare_exchange(&self,
                                         current: $int_type,
                                         new: $int_type,
@@ -1693,7 +1693,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
 }
 
 #[inline]
-#[cfg(any(stage0, target_has_atomic = "cas"))]
+#[cfg(target_has_atomic = "cas")]
 fn strongest_failure_ordering(order: Ordering) -> Ordering {
     match order {
         Release => Relaxed,
@@ -1730,7 +1730,7 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(any(stage0, target_has_atomic = "cas"))]
+#[cfg(target_has_atomic = "cas")]
 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xchg_acq(dst, val),
@@ -1769,7 +1769,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(any(stage0, target_has_atomic = "cas"))]
+#[cfg(target_has_atomic = "cas")]
 unsafe fn atomic_compare_exchange<T>(dst: *mut T,
                                      old: T,
                                      new: T,
index 1fc975cb178819d9584c8c3604ea36fab5b93a08..121f93b666bcecbe3dbe4e180e1a68e5fa33473b 100644 (file)
@@ -86,7 +86,7 @@ pub fn with_executor<'b, E>(&'b mut self, executor: &'b mut E) -> Context<'b>
     {
         Context {
             local_waker: self.local_waker,
-            executor: executor,
+            executor,
         }
     }
 }
index 321b432d3f4307b7c29681caddda75b5453bf2c3..d770536ef4279aebad5730209851c70ae0d63ec4 100644 (file)
@@ -42,7 +42,7 @@ impl Waker {
     /// `Arc` type and the safe `Wake` trait.
     #[inline]
     pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
-        Waker { inner: inner }
+        Waker { inner }
     }
 
     /// Wake up the task associated with this `Waker`.
@@ -120,7 +120,7 @@ impl LocalWaker {
     /// on the current thread.
     #[inline]
     pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
-        LocalWaker { inner: inner }
+        LocalWaker { inner }
     }
 
     /// Wake up the task associated with this `LocalWaker`.
@@ -159,7 +159,9 @@ pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
 impl From<LocalWaker> for Waker {
     #[inline]
     fn from(local_waker: LocalWaker) -> Self {
-        Waker { inner: local_waker.inner }
+        let inner = local_waker.inner;
+        mem::forget(local_waker);
+        Waker { inner }
     }
 }
 
index d2a9ed75be658abd1de4a8b2920700ede283ecb6..3d99c8ea9e22913aaac335c25d52ab08d33bad63 100644 (file)
@@ -148,9 +148,10 @@ fn test_is_control() {
 }
 
 #[test]
-fn test_is_digit() {
+fn test_is_numeric() {
    assert!('2'.is_numeric());
    assert!('7'.is_numeric());
+   assert!('¾'.is_numeric());
    assert!(!'c'.is_numeric());
    assert!(!'i'.is_numeric());
    assert!(!'z'.is_numeric());
@@ -363,54 +364,3 @@ fn check(c: char) {
     check('\u{12340}');
     check('\u{10FFFF}');
 }
-
-#[test]
-#[allow(deprecated)]
-fn test_decode_utf8() {
-    macro_rules! assert_decode_utf8 {
-        ($input_bytes: expr, $expected_str: expr) => {
-            let input_bytes: &[u8] = &$input_bytes;
-            let s = char::decode_utf8(input_bytes.iter().cloned())
-                .map(|r_b| r_b.unwrap_or('\u{FFFD}'))
-                .collect::<String>();
-            assert_eq!(s, $expected_str,
-                       "input bytes: {:?}, expected str: {:?}, result: {:?}",
-                       input_bytes, $expected_str, s);
-            assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
-        }
-    }
-
-    assert_decode_utf8!([], "");
-    assert_decode_utf8!([0x41], "A");
-    assert_decode_utf8!([0xC1, 0x81], "��");
-    assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥");
-    assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
-    assert_decode_utf8!([0xE2, 0x99], "�");
-    assert_decode_utf8!([0xE2, 0x99, 0x41], "�A");
-    assert_decode_utf8!([0xC0], "�");
-    assert_decode_utf8!([0xC0, 0x41], "�A");
-    assert_decode_utf8!([0x80], "�");
-    assert_decode_utf8!([0x80, 0x41], "�A");
-    assert_decode_utf8!([0xFE], "�");
-    assert_decode_utf8!([0xFE, 0x41], "�A");
-    assert_decode_utf8!([0xFF], "�");
-    assert_decode_utf8!([0xFF, 0x41], "�A");
-    assert_decode_utf8!([0xC0, 0x80], "��");
-
-    // Surrogates
-    assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
-    assert_decode_utf8!([0xED, 0xA0, 0x80], "���");
-    assert_decode_utf8!([0xED, 0xBF, 0x80], "���");
-    assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
-
-    // char::MAX
-    assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
-    assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "�A");
-    assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "����");
-
-    // 5 and 6 bytes sequence
-    // Part of the original design of UTF-8,
-    // but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
-    assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "�����");
-    assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "������");
-}
index 2b37acdfe3e81386d4a4c3b5d6a7bb606df29e3d..7968521f7b461ee841d5747a524cf2777c67413b 100644 (file)
@@ -390,6 +390,132 @@ fn test_windows_zip() {
     assert_eq!(res, [14, 18, 22, 26]);
 }
 
+#[test]
+#[allow(const_err)]
+fn test_iter_ref_consistency() {
+    use std::fmt::Debug;
+
+    fn test<T : Copy + Debug + PartialEq>(x : T) {
+        let v : &[T] = &[x, x, x];
+        let v_ptrs : [*const T; 3] = match v {
+            [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _],
+            _ => unreachable!()
+        };
+        let len = v.len();
+
+        // nth(i)
+        for i in 0..len {
+            assert_eq!(&v[i] as *const _, v_ptrs[i]); // check the v_ptrs array, just to be sure
+            let nth = v.iter().nth(i).unwrap();
+            assert_eq!(nth as *const _, v_ptrs[i]);
+        }
+        assert_eq!(v.iter().nth(len), None, "nth(len) should return None");
+
+        // stepping through with nth(0)
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let next = it.nth(0).unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.nth(0), None);
+        }
+
+        // next()
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let next = it.next().unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next(), None, "The final call to next() should return None");
+        }
+
+        // next_back()
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let prev = it.next_back().unwrap();
+                assert_eq!(prev as *const _, v_ptrs[remaining-1]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
+        }
+    }
+
+    fn test_mut<T : Copy + Debug + PartialEq>(x : T) {
+        let v : &mut [T] = &mut [x, x, x];
+        let v_ptrs : [*mut T; 3] = match v {
+            [ref v1, ref v2, ref v3] =>
+              [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _],
+            _ => unreachable!()
+        };
+        let len = v.len();
+
+        // nth(i)
+        for i in 0..len {
+            assert_eq!(&mut v[i] as *mut _, v_ptrs[i]); // check the v_ptrs array, just to be sure
+            let nth = v.iter_mut().nth(i).unwrap();
+            assert_eq!(nth as *mut _, v_ptrs[i]);
+        }
+        assert_eq!(v.iter().nth(len), None, "nth(len) should return None");
+
+        // stepping through with nth(0)
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let next = it.nth(0).unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.nth(0), None);
+        }
+
+        // next()
+        {
+            let mut it = v.iter_mut();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let next = it.next().unwrap();
+                assert_eq!(next as *mut _, v_ptrs[i]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next(), None, "The final call to next() should return None");
+        }
+
+        // next_back()
+        {
+            let mut it = v.iter_mut();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let prev = it.next_back().unwrap();
+                assert_eq!(prev as *mut _, v_ptrs[remaining-1]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
+        }
+    }
+
+    // Make sure iterators and slice patterns yield consistent addresses for various types,
+    // including ZSTs.
+    test(0u32);
+    test(());
+    test([0u32; 0]); // ZST with alignment > 0
+    test_mut(0u32);
+    test_mut(());
+    test_mut([0u32; 0]); // ZST with alignment > 0
+}
+
 // The current implementation of SliceIndex fails to handle methods
 // orthogonally from range types; therefore, it is worth testing
 // all of the indexing operations on each input.
index 54973b7b7783a5e1240c6f3ee5031f89b7c2ae2f..b58920224eb702217dd6009740fe5c11b0ea0ae7 100644 (file)
@@ -91,7 +91,7 @@ pub fn new(secs: u64, nanos: u32) -> Duration {
         let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64)
             .expect("overflow in Duration::new");
         let nanos = nanos % NANOS_PER_SEC;
-        Duration { secs: secs, nanos: nanos }
+        Duration { secs, nanos }
     }
 
     /// Creates a new `Duration` from the specified number of whole seconds.
@@ -109,7 +109,7 @@ pub fn new(secs: u64, nanos: u32) -> Duration {
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
     pub const fn from_secs(secs: u64) -> Duration {
-        Duration { secs: secs, nanos: 0 }
+        Duration { secs, nanos: 0 }
     }
 
     /// Creates a new `Duration` from the specified number of milliseconds.
@@ -387,7 +387,7 @@ pub fn checked_sub(self, rhs: Duration) -> Option<Duration> {
                 }
             };
             debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration { secs: secs, nanos: nanos })
+            Some(Duration { secs, nanos })
         } else {
             None
         }
@@ -453,7 +453,7 @@ pub fn checked_div(self, rhs: u32) -> Option<Duration> {
             let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
             let nanos = self.nanos / rhs + (extra_nanos as u32);
             debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration { secs: secs, nanos: nanos })
+            Some(Duration { secs, nanos })
         } else {
             None
         }
index 32668ea93dd8c18a62df7a8cc59d844a52aa93a9..3de855ac943157091696c035096c70399d5bd96e 100644 (file)
@@ -40,7 +40,7 @@ pub fn Cc(c: char) -> bool {
 
     pub const N_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
-            0x03ff000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+            0x03ff000000000000, 0x0000000000000000, 0x720c000000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
@@ -50,12 +50,14 @@ pub fn Cc(c: char) -> bool {
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x00000000000003ff
         ],
         r2: [
-            0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 2, 3,
-            0, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 5, 0, 0, 0, 3, 2, 0, 0, 0, 0, 6, 0, 2, 0, 0, 7, 0, 0, 2, 8, 0, 0, 7, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 1, 0, 2, 0, 1, 0, 1, 0, 3, 0, 4, 0, 5, 0, 1, 0, 6, 0, 1, 0, 7, 0, 7, 8,
+            0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 11, 0, 0, 0, 12, 7, 0, 0, 0, 0, 13, 0, 14, 0, 0, 15, 0, 0, 7, 16, 0, 0, 15, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 9, 0, 0, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 27, 0, 28,
+            29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -69,10 +71,10 @@ pub fn Cc(c: char) -> bool {
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,
+            0, 0, 1, 0, 0, 0, 0, 31, 0, 0, 7, 9, 0, 0, 32, 0, 7, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0,
-            0, 0, 0, 0, 0, 2, 4, 0, 0, 12, 0, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -82,18 +84,21 @@ pub fn Cc(c: char) -> bool {
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 2, 0, 0, 0
+            0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0
         ],
         r3: &[
-            0x0000000000000000, 0x0000ffc000000000, 0x0000000003ff0000, 0x000003ff00000000,
-            0x00000000000003ff, 0x0001c00000000000, 0x000000000000ffc0, 0x0000000003ff03ff,
-            0x03ff000000000000, 0xffffffff00000000, 0x00000000000001e7, 0x070003fe00000080,
+            0x0000000000000000, 0x0000ffc000000000, 0x03f0ffc000000000, 0x00fcffc000000000,
+            0x0007ffc000000000, 0x7f00ffc000000000, 0x01ffffc07f000000, 0x0000000003ff0000,
+            0x000fffff00000000, 0x00000000000003ff, 0x1ffffe0000000000, 0x0001c00000000000,
+            0x03ff03ff00000000, 0x000000000000ffc0, 0x0000000007ff0000, 0x0000000003ff03ff,
+            0x03ff000000000000, 0x03f1000000000000, 0xffffffffffff0000, 0x00000000000003e7,
+            0xffffffff00000000, 0x000000000fffffff, 0xfffffc0000000000, 0xffc0000000000000,
+            0x00000000000fffff, 0x2000000000000000, 0x070003fe00000080, 0x00000000003c0000,
+            0x000003ff00000000, 0x00000000fffeff00, 0xfffe0000000003ff, 0x003f000000000000,
             0x03ff000003ff0000
         ],
         r4: [
-            0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+            0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -104,28 +109,37 @@ pub fn Cc(c: char) -> bool {
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
         ],
         r5: &[
-            0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 6, 0, 5, 7, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0,
-            0, 0, 8, 0, 9, 5, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0,
-            0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
-            11, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 9, 10, 11, 12, 0, 13, 14, 0, 15, 16, 17, 0, 18, 19, 0, 0, 0, 0, 20, 21, 0,
+            0, 0, 0, 22, 0, 0, 23, 24, 0, 0, 0, 25, 0, 21, 26, 0, 0, 27, 0, 0, 0, 21, 0, 0, 0, 0, 0,
+            28, 0, 28, 0, 0, 0, 0, 0, 28, 0, 29, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 32, 0, 0, 0, 28, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 33, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 28, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
         ],
         r6: &[
-            0x0000000000000000, 0x001fffffffffffff, 0x0000000000000402, 0x00000000003e0000,
-            0x000003ff00000000, 0x03ff000000000000, 0x0000ffc000000000, 0xffc0000000000000,
-            0x0000000003ff0000, 0x00000000000003ff, 0xffffffffffffffff, 0x00007fffffffffff,
-            0xffffffffffffc000
+            0x0000000000000000, 0x000fffffffffff80, 0x01ffffffffffffff, 0x0000000000000c00,
+            0x0ffffffe00000000, 0x0000000f00000000, 0x0000000000000402, 0x00000000003e0000,
+            0x000003ff00000000, 0xfe000000ff000000, 0x0000ff8000000000, 0xf800000000000000,
+            0x000000000fc00000, 0x3000000000000000, 0xfffffffffffcffff, 0x60000000000001ff,
+            0x00000000e0000000, 0x0000f80000000000, 0xff000000ff000000, 0x0000fe0000000000,
+            0xfc00000000000000, 0x03ff000000000000, 0x7fffffff00000000, 0x0000007fe0000000,
+            0x00000000001e0000, 0x0000fffffffc0000, 0xffc0000000000000, 0x001ffffe03ff0000,
+            0x0000000003ff0000, 0x00000000000003ff, 0x0fff000000000000, 0x0007ffff00000000,
+            0x00001fffffff0000, 0xffffffffffffffff, 0x00007fffffffffff, 0x00000003fbff0000,
+            0x00000000007fffff, 0x000fffff00000000, 0x01ffffff00000000, 0xffffffffffffc000,
+            0x000000000000ff80, 0xfffe000000000000, 0x001eefffffffffff, 0x0000000000001fff
         ],
     };
 
index be0970b544406e5ac9cfe6e2d0b41bb4aa76217a..28a1e01805e46d9a502cb3b84ac6c2f0a02fb8dc 100755 (executable)
@@ -52,7 +52,7 @@ expanded_categories = {
     'Lu': ['LC', 'L'], 'Ll': ['LC', 'L'], 'Lt': ['LC', 'L'],
     'Lm': ['L'], 'Lo': ['L'],
     'Mn': ['M'], 'Mc': ['M'], 'Me': ['M'],
-    'Nd': ['N'], 'Nl': ['N'], 'No': ['No'],
+    'Nd': ['N'], 'Nl': ['N'], 'No': ['N'],
     'Pc': ['P'], 'Pd': ['P'], 'Ps': ['P'], 'Pe': ['P'],
     'Pi': ['P'], 'Pf': ['P'], 'Po': ['P'],
     'Sm': ['S'], 'Sc': ['S'], 'Sk': ['S'], 'So': ['S'],
index 1c355e35fd6eafffbc048e23c6fe21dae2874291..cb5e1e600d3d2e8659b21d7bdcc8cc84231dd5a3 100644 (file)
@@ -49,6 +49,7 @@ pub enum Def {
     PrimTy(hir::PrimTy),
     TyParam(DefId),
     SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
+    ToolMod, // e.g. `rustfmt` in `#[rustfmt::skip]`
 
     // Value namespace
     Fn(DefId),
@@ -67,6 +68,7 @@ pub enum Def {
 
     // Macro namespace
     Macro(DefId, MacroKind),
+    NonMacroAttr, // e.g. `#[inline]` or `#[rustfmt::skip]`
 
     GlobalAsm(DefId),
 
@@ -259,6 +261,8 @@ pub fn def_id(&self) -> DefId {
             Def::Label(..)  |
             Def::PrimTy(..) |
             Def::SelfTy(..) |
+            Def::ToolMod |
+            Def::NonMacroAttr |
             Def::Err => {
                 bug!("attempted .def_id() on invalid def: {:?}", self)
             }
@@ -299,6 +303,8 @@ pub fn kind_name(&self) -> &'static str {
             Def::SelfTy(..) => "self type",
             Def::Macro(.., macro_kind) => macro_kind.descr(),
             Def::GlobalAsm(..) => "global asm",
+            Def::ToolMod => "tool module",
+            Def::NonMacroAttr => "non-macro attribute",
             Def::Err => "unresolved item",
         }
     }
index 63755bcea5e62f293d923be13efc7fb8d22ecbd6..4b69e3b6bc70db8d0db5ba99597f68e0b9f649d6 100644 (file)
@@ -3753,16 +3753,14 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             }
             // Desugar `<start>..=<end>` to `std::ops::RangeInclusive::new(<start>, <end>)`
             ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
-                // FIXME: Use e.span directly after RangeInclusive::new() is stabilized in stage0.
-                let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
                 let id = self.next_id();
                 let e1 = self.lower_expr(e1);
                 let e2 = self.lower_expr(e2);
-                let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], None, false));
-                let ty = P(self.ty_path(id, span, hir::QPath::Resolved(None, ty_path)));
+                let ty_path = P(self.std_path(e.span, &["ops", "RangeInclusive"], None, false));
+                let ty = P(self.ty_path(id, e.span, hir::QPath::Resolved(None, ty_path)));
                 let new_seg = P(hir::PathSegment::from_ident(Ident::from_str("new")));
                 let new_path = hir::QPath::TypeRelative(ty, new_seg);
-                let new = P(self.expr(span, hir::ExprKind::Path(new_path), ThinVec::new()));
+                let new = P(self.expr(e.span, hir::ExprKind::Path(new_path), ThinVec::new()));
                 hir::ExprKind::Call(new, hir_vec![e1, e2])
             }
             ExprKind::Range(ref e1, ref e2, lims) => {
@@ -3785,20 +3783,16 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     .chain(e2.iter().map(|e| ("end", e)))
                     .map(|(s, e)| {
                         let expr = P(self.lower_expr(&e));
-                        let unstable_span =
-                            self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
-                        let ident = Ident::new(Symbol::intern(s), unstable_span);
-                        self.field(ident, expr, unstable_span)
+                        let ident = Ident::new(Symbol::intern(s), e.span);
+                        self.field(ident, expr, e.span)
                     })
                     .collect::<P<[hir::Field]>>();
 
                 let is_unit = fields.is_empty();
-                let unstable_span =
-                    self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
                 let struct_path = iter::once("ops")
                     .chain(iter::once(path))
                     .collect::<Vec<_>>();
-                let struct_path = self.std_path(unstable_span, &struct_path, None, is_unit);
+                let struct_path = self.std_path(e.span, &struct_path, None, is_unit);
                 let struct_path = hir::QPath::Resolved(None, P(struct_path));
 
                 let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id);
@@ -3811,7 +3805,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     } else {
                         hir::ExprKind::Struct(struct_path, fields, None)
                     },
-                    span: unstable_span,
+                    span: e.span,
                     attrs: e.attrs.clone(),
                 };
             }
index 410d578d4044c9524101d400402e9fd53e9ffe37..cac0d182d3a48923c43ad897e4c7ab32dc0cf4a1 100644 (file)
@@ -1016,6 +1016,8 @@ fn to_stable_hash_key(&self,
     Label(node_id),
     Macro(def_id, macro_kind),
     GlobalAsm(def_id),
+    ToolMod,
+    NonMacroAttr,
     Err
 });
 
index c106966fb70be0041ef576f32d1ff6d220d39a11..2ab0124397bbb1b1a8749e153e5ef6057a77f9a2 100644 (file)
@@ -409,7 +409,6 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
 
 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
     Async,
-    DotFill,
     QuestionMark,
     ExistentialReturnType,
     ForLoop,
index cb685f83aba1eb670852fcb33970e6fb4a5a98f8..f13e26fee3ee460aa80a5c1201ea50dd86094af3 100644 (file)
@@ -392,6 +392,11 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl_stable_hash_for!(enum mir::interpret::ScalarMaybeUndef {
+    Scalar(v),
+    Undef
+});
+
 impl_stable_hash_for!(enum mir::interpret::Value {
     Scalar(v),
     ScalarPair(a, b),
@@ -466,9 +471,9 @@ fn hash_stable<W: StableHasherResult>(&self,
 
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
-            Bits { bits, defined } => {
+            Bits { bits, size } => {
                 bits.hash_stable(hcx, hasher);
-                defined.hash_stable(hcx, hasher);
+                size.hash_stable(hcx, hasher);
             },
             Ptr(ptr) => ptr.hash_stable(hcx, hasher),
         }
index 8e71df3c34b0b42b998aeb7a8d24e477cda6249d..bac511aac1fe10108f01adb76258d4df01fdcbdf 100644 (file)
@@ -165,6 +165,7 @@ pub mod util {
     pub mod nodemap;
     pub mod fs;
     pub mod time_graph;
+    pub mod profiling;
 }
 
 // A private module so that macro-expanded idents like
index 14cfaa8153377d76f1adbdcc6c5acac35ffc2a66..15630157722fa502ea3c715648c4ad01f7508914 100644 (file)
@@ -42,7 +42,7 @@
 use std::default::Default as StdDefault;
 use syntax::ast;
 use syntax::edition;
-use syntax_pos::{MultiSpan, Span};
+use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString};
 use errors::DiagnosticBuilder;
 use hir;
 use hir::def_id::LOCAL_CRATE;
@@ -133,6 +133,12 @@ pub enum CheckLintNameResult<'a> {
     /// The lint is either renamed or removed. This is the warning
     /// message, and an optional new name (`None` if removed).
     Warning(String, Option<String>),
+    /// The lint is from a tool. If the Option is None, then either
+    /// the lint does not exist in the tool or the code was not
+    /// compiled with the tool and therefore the lint was never
+    /// added to the `LintStore`. Otherwise the `LintId` will be
+    /// returned as if it where a rustc lint.
+    Tool(Option<&'a [LintId]>),
 }
 
 impl LintStore {
@@ -288,7 +294,7 @@ pub fn check_lint_name_cmdline(&self,
                                    sess: &Session,
                                    lint_name: &str,
                                    level: Level) {
-        let db = match self.check_lint_name(lint_name) {
+        let db = match self.check_lint_name(lint_name, None) {
             CheckLintNameResult::Ok(_) => None,
             CheckLintNameResult::Warning(ref msg, _) => {
                 Some(sess.struct_warn(msg))
@@ -296,6 +302,7 @@ pub fn check_lint_name_cmdline(&self,
             CheckLintNameResult::NoLint => {
                 Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
             }
+            CheckLintNameResult::Tool(_) => unreachable!(),
         };
 
         if let Some(mut db) = db {
@@ -319,26 +326,41 @@ pub fn check_lint_name_cmdline(&self,
     /// it emits non-fatal warnings and there are *two* lint passes that
     /// inspect attributes, this is only run from the late pass to avoid
     /// printing duplicate warnings.
-    pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult {
-        match self.by_name.get(lint_name) {
-            Some(&Renamed(ref new_name, _)) => {
-                CheckLintNameResult::Warning(
-                    format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
-                    Some(new_name.to_owned())
-                )
-            },
-            Some(&Removed(ref reason)) => {
-                CheckLintNameResult::Warning(
-                    format!("lint `{}` has been removed: `{}`", lint_name, reason),
-                    None
-                )
-            },
-            None => {
-                match self.lint_groups.get(lint_name) {
-                    None => CheckLintNameResult::NoLint,
-                    Some(ids) => CheckLintNameResult::Ok(&ids.0),
-                }
+    pub fn check_lint_name(
+        &self,
+        lint_name: &str,
+        tool_name: Option<LocalInternedString>,
+    ) -> CheckLintNameResult {
+        let complete_name = if let Some(tool_name) = tool_name {
+            format!("{}::{}", tool_name, lint_name)
+        } else {
+            lint_name.to_string()
+        };
+        if let Some(_) = tool_name {
+            match self.by_name.get(&complete_name) {
+                None => match self.lint_groups.get(&*complete_name) {
+                    None => return CheckLintNameResult::Tool(None),
+                    Some(ids) => return CheckLintNameResult::Tool(Some(&ids.0)),
+                },
+                Some(&Id(ref id)) => return CheckLintNameResult::Tool(Some(slice::from_ref(id))),
+                // If the lint was registered as removed or renamed by the lint tool, we don't need
+                // to treat tool_lints and rustc lints different and can use the code below.
+                _ => {}
             }
+        }
+        match self.by_name.get(&complete_name) {
+            Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
+                format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
+                Some(new_name.to_owned()),
+            ),
+            Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
+                format!("lint `{}` has been removed: `{}`", lint_name, reason),
+                None,
+            ),
+            None => match self.lint_groups.get(&*complete_name) {
+                None => CheckLintNameResult::NoLint,
+                Some(ids) => CheckLintNameResult::Ok(&ids.0),
+            },
             Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
         }
     }
index b7b6aba970bff21c76a07c1e3f7a65913a7fec5e..483e2ea8a96cd8607c51deab2f0717e301355e66 100644 (file)
@@ -227,8 +227,10 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                         continue
                     }
                 };
-                if let Some(lint_tool) = word.is_scoped() {
-                    if !self.sess.features_untracked().tool_lints {
+                let tool_name = if let Some(lint_tool) = word.is_scoped() {
+                    let gate_feature = !self.sess.features_untracked().tool_lints;
+                    let known_tool = attr::is_known_lint_tool(lint_tool);
+                    if gate_feature {
                         feature_gate::emit_feature_err(&sess.parse_sess,
                                                        "tool_lints",
                                                        word.span,
@@ -236,8 +238,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                                                        &format!("scoped lint `{}` is experimental",
                                                                 word.ident));
                     }
-
-                    if !attr::is_known_lint_tool(lint_tool) {
+                    if !known_tool {
                         span_err!(
                             sess,
                             lint_tool.span,
@@ -247,10 +248,16 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                         );
                     }
 
-                    continue
-                }
+                    if gate_feature || !known_tool {
+                        continue
+                    }
+
+                    Some(lint_tool.as_str())
+                } else {
+                    None
+                };
                 let name = word.name();
-                match store.check_lint_name(&name.as_str()) {
+                match store.check_lint_name(&name.as_str(), tool_name) {
                     CheckLintNameResult::Ok(ids) => {
                         let src = LintSource::Node(name, li.span);
                         for id in ids {
@@ -258,6 +265,20 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                         }
                     }
 
+                    CheckLintNameResult::Tool(result) => {
+                        if let Some(ids) = result {
+                            let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
+                            let src = LintSource::Node(Symbol::intern(complete_name), li.span);
+                            for id in ids {
+                                specs.insert(*id, (level, src));
+                            }
+                        }
+                        // If Tool(None) is returned, then either the lint does not exist in the
+                        // tool or the code was not compiled with the tool and therefore the lint
+                        // was never added to the `LintStore`. To detect this is the responsibility
+                        // of the lint tool.
+                    }
+
                     _ if !self.warn_about_weird_lints => {}
 
                     CheckLintNameResult::Warning(msg, renamed) => {
@@ -298,7 +319,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                         if name.as_str().chars().any(|c| c.is_uppercase()) {
                             let name_lower = name.as_str().to_lowercase().to_string();
                             if let CheckLintNameResult::NoLint =
-                                    store.check_lint_name(&name_lower) {
+                                    store.check_lint_name(&name_lower, tool_name) {
                                 db.emit();
                             } else {
                                 db.span_suggestion_with_applicability(
index 3c1b20562089200aa9e1989f8855d193d487b714..d267c1812773b07ab6116b4bd3851af2326a6c7e 100644 (file)
@@ -139,6 +139,26 @@ macro_rules! declare_lint {
     );
 }
 
+#[macro_export]
+macro_rules! declare_tool_lint {
+    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => (
+        declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false}
+    );
+    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr,
+     report_in_external_macro: $rep: expr) => (
+         declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep}
+    );
+    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
+        $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
+            name: &concat!(stringify!($tool), "::", stringify!($NAME)),
+            default_level: $crate::lint::$Level,
+            desc: $desc,
+            edition_lint_opts: None,
+            report_in_external_macro: $external,
+        };
+    );
+}
+
 /// Declare a static `LintArray` and return it as an expression.
 #[macro_export]
 macro_rules! lint_array {
@@ -575,7 +595,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
     // Check for future incompatibility lints and issue a stronger warning.
     let lints = sess.lint_store.borrow();
     let lint_id = LintId::of(lint);
-    if let Some(future_incompatible) = lints.future_incompatible(lint_id) {
+    let future_incompatible = lints.future_incompatible(lint_id);
+    if let Some(future_incompatible) = future_incompatible {
         const STANDARD_MESSAGE: &str =
             "this was previously accepted by the compiler but is being phased out; \
              it will become a hard error";
@@ -593,20 +614,21 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
                                future_incompatible.reference);
         err.warn(&explanation);
         err.note(&citation);
+    }
 
-    // If this lint is *not* a future incompatibility warning then we want to be
-    // sure to not be too noisy in some situations. If this code originates in a
-    // foreign macro, aka something that this crate did not itself author, then
-    // it's likely that there's nothing this crate can do about it. We probably
-    // want to skip the lint entirely.
-    //
-    // For some lints though (like unreachable code) there's clear actionable
-    // items to take care of (delete the macro invocation). As a result we have
-    // a few lints we whitelist here for allowing a lint even though it's in a
-    // foreign macro invocation.
-    } else if !lint.report_in_external_macro {
-        if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
-            err.cancel();
+    // If this code originates in a foreign macro, aka something that this crate
+    // did not itself author, then it's likely that there's nothing this crate
+    // can do about it. We probably want to skip the lint entirely.
+    if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
+        // Any suggestions made here are likely to be incorrect, so anything we
+        // emit shouldn't be automatically fixed by rustfix.
+        err.allow_suggestions(false);
+
+        // If this is a future incompatible lint it'll become a hard error, so
+        // we have to emit *something*. Also allow lints to whitelist themselves
+        // on a case-by-case basis for emission in a foreign macro.
+        if future_incompatible.is_none() && !lint.report_in_external_macro {
+            err.cancel()
         }
     }
 
index 54169acac46acabb00e36be540a6f64aa9e58591..0e84104245dcb14a78ae3f1d2be8cfa1eb54bae5 100644 (file)
 //! are *mostly* used as a part of that interface, but these should
 //! probably get a better home if someone can find one.
 
-use hir::def;
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use hir::map as hir_map;
-use hir::map::definitions::{Definitions, DefKey, DefPathTable};
+use hir::map::definitions::{DefKey, DefPathTable};
 use hir::svh::Svh;
 use ty::{self, TyCtxt};
 use session::{Session, CrateDisambiguator};
@@ -34,8 +33,6 @@
 use std::any::Any;
 use std::path::{Path, PathBuf};
 use syntax::ast;
-use syntax::edition::Edition;
-use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_target::spec::Target;
@@ -140,11 +137,6 @@ pub struct ForeignModule {
     pub def_id: DefId,
 }
 
-pub enum LoadedMacro {
-    MacroDef(ast::Item),
-    ProcMacro(Lrc<SyntaxExtension>),
-}
-
 #[derive(Copy, Clone, Debug)]
 pub struct ExternCrate {
     pub src: ExternCrateSource,
@@ -221,9 +213,6 @@ fn get_dylib_metadata(&self,
 pub trait CrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>;
 
-    // access to the metadata loader
-    fn metadata_loader(&self) -> &dyn MetadataLoader;
-
     // resolve
     fn def_key(&self, def: DefId) -> DefKey;
     fn def_path(&self, def: DefId) -> hir_map::DefPath;
@@ -231,19 +220,11 @@ pub trait CrateStore {
     fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable>;
 
     // "queries" used in resolve that aren't tracked for incremental compilation
-    fn visibility_untracked(&self, def: DefId) -> ty::Visibility;
-    fn export_macros_untracked(&self, cnum: CrateNum);
-    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind;
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
     fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
-    fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition;
-    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>;
-    fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
-    fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
     fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
     fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
-    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
     fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
 
     // This is basically a 1-based range of ints, which is a little
@@ -260,116 +241,6 @@ fn encode_metadata<'a, 'tcx>(&self,
 
 pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
 
-// FIXME: find a better place for this?
-pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
-    let mut err_count = 0;
-    {
-        let mut say = |s: &str| {
-            match (sp, sess) {
-                (_, None) => bug!("{}", s),
-                (Some(sp), Some(sess)) => sess.span_err(sp, s),
-                (None, Some(sess)) => sess.err(s),
-            }
-            err_count += 1;
-        };
-        if s.is_empty() {
-            say("crate name must not be empty");
-        }
-        for c in s.chars() {
-            if c.is_alphanumeric() { continue }
-            if c == '_'  { continue }
-            say(&format!("invalid character `{}` in crate name: `{}`", c, s));
-        }
-    }
-
-    if err_count > 0 {
-        sess.unwrap().abort_if_errors();
-    }
-}
-
-/// A dummy crate store that does not support any non-local crates,
-/// for test purposes.
-pub struct DummyCrateStore;
-
-#[allow(unused_variables)]
-impl CrateStore for DummyCrateStore {
-    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>
-        { bug!("crate_data_as_rc_any") }
-    // item info
-    fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
-    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics
-        { bug!("item_generics_cloned") }
-
-    // trait/impl-item info
-    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
-        { bug!("associated_item_cloned") }
-
-    // crate metadata
-    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
-    fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") }
-    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") }
-    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator {
-        bug!("crate_disambiguator")
-    }
-    fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") }
-    fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { bug!("crate_edition_untracked") }
-
-    // resolve
-    fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
-    fn def_path(&self, def: DefId) -> hir_map::DefPath {
-        bug!("relative_def_path")
-    }
-    fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash {
-        bug!("def_path_hash")
-    }
-    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable> {
-        bug!("def_path_table")
-    }
-    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
-        bug!("struct_field_names")
-    }
-    fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export> {
-        bug!("item_children")
-    }
-    fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }
-
-    fn crates_untracked(&self) -> Vec<CrateNum> { vec![] }
-
-    // utility functions
-    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
-    fn encode_metadata<'a, 'tcx>(&self,
-                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 link_meta: &LinkMeta)
-                                 -> EncodedMetadata {
-        bug!("encode_metadata")
-    }
-    fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
-    fn postorder_cnums_untracked(&self) -> Vec<CrateNum> { bug!("postorder_cnums_untracked") }
-
-    // access to the metadata loader
-    fn metadata_loader(&self) -> &dyn MetadataLoader { bug!("metadata_loader") }
-}
-
-pub trait CrateLoader {
-    fn process_extern_crate(&mut self, item: &ast::Item, defs: &Definitions) -> CrateNum;
-
-    fn process_path_extern(
-        &mut self,
-        name: Symbol,
-        span: Span,
-    ) -> CrateNum;
-
-    fn process_use_extern(
-        &mut self,
-        name: Symbol,
-        span: Span,
-        id: ast::NodeId,
-        defs: &Definitions,
-    ) -> CrateNum;
-
-    fn postprocess(&mut self, krate: &ast::Crate);
-}
-
 // This method is used when generating the command line to pass through to
 // system linker. The linker expects undefined symbols on the left of the
 // command line to be defined in libraries on the right, not the other way
index 4c99b46ddff6e5443cd3f9af9ffc84c3c91612df..a9c118d606b2eb1584a7d8dd9a546cb74e16c935 100644 (file)
@@ -115,30 +115,30 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let preferred_linkage = match ty {
         // cdylibs must have all static dependencies.
-        config::CrateTypeCdylib => Linkage::Static,
+        config::CrateType::Cdylib => Linkage::Static,
 
         // Generating a dylib without `-C prefer-dynamic` means that we're going
         // to try to eagerly statically link all dependencies. This is normally
         // done for end-product dylibs, not intermediate products.
-        config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
-        config::CrateTypeDylib => Linkage::Dynamic,
+        config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
+        config::CrateType::Dylib => Linkage::Dynamic,
 
         // If the global prefer_dynamic switch is turned off, or the final
         // executable will be statically linked, prefer static crate linkage.
-        config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic ||
+        config::CrateType::Executable if !sess.opts.cg.prefer_dynamic ||
             sess.crt_static() => Linkage::Static,
-        config::CrateTypeExecutable => Linkage::Dynamic,
+        config::CrateType::Executable => Linkage::Dynamic,
 
         // proc-macro crates are required to be dylibs, and they're currently
         // required to link to libsyntax as well.
-        config::CrateTypeProcMacro => Linkage::Dynamic,
+        config::CrateType::ProcMacro => Linkage::Dynamic,
 
         // No linkage happens with rlibs, we just needed the metadata (which we
         // got long ago), so don't bother with anything.
-        config::CrateTypeRlib => Linkage::NotLinked,
+        config::CrateType::Rlib => Linkage::NotLinked,
 
         // staticlibs must have all static dependencies.
-        config::CrateTypeStaticlib => Linkage::Static,
+        config::CrateType::Staticlib => Linkage::Static,
     };
 
     if preferred_linkage == Linkage::NotLinked {
@@ -155,8 +155,8 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Staticlibs, cdylibs, and static executables must have all static
         // dependencies. If any are not found, generate some nice pretty errors.
-        if ty == config::CrateTypeCdylib || ty == config::CrateTypeStaticlib ||
-                (ty == config::CrateTypeExecutable && sess.crt_static() &&
+        if ty == config::CrateType::Cdylib || ty == config::CrateType::Staticlib ||
+                (ty == config::CrateType::Executable && sess.crt_static() &&
                 !sess.target.target.options.crt_static_allows_dylibs) {
             for &cnum in tcx.crates().iter() {
                 if tcx.dep_kind(cnum).macros_only() { continue }
index feeb508d676c94e726a119e9e3f045de07c602a8..b0acc6f20e691f56a0c13070ef9203d9fa87776a 100644 (file)
@@ -12,6 +12,7 @@
 use hir::map as hir_map;
 use hir::def_id::{CRATE_DEF_INDEX};
 use session::{config, Session};
+use session::config::EntryFnType;
 use syntax::ast::NodeId;
 use syntax::attr;
 use syntax::entry::EntryPointType;
@@ -59,7 +60,7 @@ pub fn find_entry_point(session: &Session,
                         hir_map: &hir_map::Map,
                         crate_name: &str) {
     let any_exe = session.crate_types.borrow().iter().any(|ty| {
-        *ty == config::CrateTypeExecutable
+        *ty == config::CrateType::Executable
     });
     if !any_exe {
         // No need to find a main function
@@ -155,11 +156,11 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
 
 fn configure_main(this: &mut EntryContext, crate_name: &str) {
     if let Some((node_id, span)) = this.start_fn {
-        this.session.entry_fn.set(Some((node_id, span, config::EntryStart)));
+        this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start)));
     } else if let Some((node_id, span)) = this.attr_main_fn {
-        this.session.entry_fn.set(Some((node_id, span, config::EntryMain)));
+        this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
     } else if let Some((node_id, span)) = this.main_fn {
-        this.session.entry_fn.set(Some((node_id, span, config::EntryMain)));
+        this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
     } else {
         // No main function
         this.session.entry_fn.set(None);
index 19c82d7d27c79a294a29e48751cafa579d44e49f..94246db37069aedb56d409b6be983842279f4182 100644 (file)
@@ -408,8 +408,8 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) ->
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
 
     let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
-        *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib ||
-        *ty == config::CrateTypeProcMacro
+        *ty == config::CrateType::Rlib || *ty == config::CrateType::Dylib ||
+        *ty == config::CrateType::ProcMacro
     });
     let mut reachable_context = ReachableContext {
         tcx,
index d8570b43fbe276dc32d86cf4baaa582cb0915da7..e8431ce3e109b4d9505fd0d96acd225d0c29fb2b 100644 (file)
@@ -89,12 +89,12 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // emitting something that's not an rlib.
     let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| {
         match *kind {
-            config::CrateTypeDylib |
-            config::CrateTypeProcMacro |
-            config::CrateTypeCdylib |
-            config::CrateTypeExecutable |
-            config::CrateTypeStaticlib => true,
-            config::CrateTypeRlib => false,
+            config::CrateType::Dylib |
+            config::CrateType::ProcMacro |
+            config::CrateType::Cdylib |
+            config::CrateType::Executable |
+            config::CrateType::Staticlib => true,
+            config::CrateType::Rlib => false,
         }
     });
     if !needs_check {
index 4164fe3fd933b80a8c65eb7c300127a94a0d4539..a0980b06230c8a05b4bdf5428e7962b1934ee81a 100644 (file)
@@ -13,7 +13,7 @@ macro_rules! err {
     FrameInfo, ConstEvalResult,
 };
 
-pub use self::value::{Scalar, Value, ConstValue};
+pub use self::value::{Scalar, Value, ConstValue, ScalarMaybeUndef};
 
 use std::fmt;
 use mir;
index ffd138c9c4815542c897c6880c8fffcdea194923..f569f4def143f8dd6af8c2b71b4cbc27ae4a6219 100644 (file)
@@ -15,22 +15,24 @@ pub enum ConstValue<'tcx> {
     /// to allow HIR creation to happen for everything before needing to be able to run constant
     /// evaluation
     Unevaluated(DefId, &'tcx Substs<'tcx>),
-    /// Used only for types with layout::abi::Scalar ABI and ZSTs which use Scalar::undef()
+    /// Used only for types with layout::abi::Scalar ABI and ZSTs
     Scalar(Scalar),
     /// Used only for types with layout::abi::ScalarPair
-    ScalarPair(Scalar, Scalar),
+    ///
+    /// The second field may be undef in case of `Option<usize>::None`
+    ScalarPair(Scalar, ScalarMaybeUndef),
     /// Used only for the remaining cases. An allocation + offset into the allocation
     ByRef(&'tcx Allocation, Size),
 }
 
 impl<'tcx> ConstValue<'tcx> {
     #[inline]
-    pub fn from_byval_value(val: Value) -> Self {
-        match val {
+    pub fn from_byval_value(val: Value) -> EvalResult<'static, Self> {
+        Ok(match val {
             Value::ByRef(..) => bug!(),
-            Value::ScalarPair(a, b) => ConstValue::ScalarPair(a, b),
-            Value::Scalar(val) => ConstValue::Scalar(val),
-        }
+            Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b),
+            Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?),
+        })
     }
 
     #[inline]
@@ -38,18 +40,13 @@ pub fn to_byval_value(&self) -> Option<Value> {
         match *self {
             ConstValue::Unevaluated(..) |
             ConstValue::ByRef(..) => None,
-            ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a, b)),
-            ConstValue::Scalar(val) => Some(Value::Scalar(val)),
+            ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a.into(), b)),
+            ConstValue::Scalar(val) => Some(Value::Scalar(val.into())),
         }
     }
 
     #[inline]
-    pub fn from_scalar(val: Scalar) -> Self {
-        ConstValue::Scalar(val)
-    }
-
-    #[inline]
-    pub fn to_scalar(&self) -> Option<Scalar> {
+    pub fn try_to_scalar(&self) -> Option<Scalar> {
         match *self {
             ConstValue::Unevaluated(..) |
             ConstValue::ByRef(..) |
@@ -60,12 +57,12 @@ pub fn to_scalar(&self) -> Option<Scalar> {
 
     #[inline]
     pub fn to_bits(&self, size: Size) -> Option<u128> {
-        self.to_scalar()?.to_bits(size).ok()
+        self.try_to_scalar()?.to_bits(size).ok()
     }
 
     #[inline]
     pub fn to_ptr(&self) -> Option<Pointer> {
-        self.to_scalar()?.to_ptr().ok()
+        self.try_to_scalar()?.to_ptr().ok()
     }
 }
 
@@ -81,8 +78,8 @@ pub fn to_ptr(&self) -> Option<Pointer> {
 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
 pub enum Value {
     ByRef(Scalar, Align),
-    Scalar(Scalar),
-    ScalarPair(Scalar, Scalar),
+    Scalar(ScalarMaybeUndef),
+    ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef),
 }
 
 impl<'tcx> ty::TypeFoldable<'tcx> for Value {
@@ -98,23 +95,27 @@ impl<'tcx> Scalar {
     pub fn ptr_null<C: HasDataLayout>(cx: C) -> Self {
         Scalar::Bits {
             bits: 0,
-            defined: cx.data_layout().pointer_size.bits() as u8,
+            size: cx.data_layout().pointer_size.bytes() as u8,
         }
     }
 
+    pub fn to_value_with_len<C: HasDataLayout>(self, len: u64, cx: C) -> Value {
+        ScalarMaybeUndef::Scalar(self).to_value_with_len(len, cx)
+    }
+
+    pub fn to_value_with_vtable(self, vtable: Pointer) -> Value {
+        ScalarMaybeUndef::Scalar(self).to_value_with_vtable(vtable)
+    }
+
     pub fn ptr_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
         let layout = cx.data_layout();
         match self {
-            Scalar::Bits { bits, defined } => {
-                let pointer_size = layout.pointer_size.bits() as u8;
-                if defined < pointer_size {
-                    err!(ReadUndefBytes)
-                } else {
-                    Ok(Scalar::Bits {
-                        bits: layout.signed_offset(bits as u64, i)? as u128,
-                        defined: pointer_size,
-                    })
-            }
+            Scalar::Bits { bits, size } => {
+                assert_eq!(size as u64, layout.pointer_size.bytes());
+                Ok(Scalar::Bits {
+                    bits: layout.signed_offset(bits as u64, i)? as u128,
+                    size,
+                })
             }
             Scalar::Ptr(ptr) => ptr.signed_offset(i, layout).map(Scalar::Ptr),
         }
@@ -123,65 +124,43 @@ pub fn ptr_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'t
     pub fn ptr_offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
         let layout = cx.data_layout();
         match self {
-            Scalar::Bits { bits, defined } => {
-                let pointer_size = layout.pointer_size.bits() as u8;
-                if defined < pointer_size {
-                    err!(ReadUndefBytes)
-                } else {
-                    Ok(Scalar::Bits {
-                        bits: layout.offset(bits as u64, i.bytes())? as u128,
-                        defined: pointer_size,
-                    })
-            }
+            Scalar::Bits { bits, size } => {
+                assert_eq!(size as u64, layout.pointer_size.bytes());
+                Ok(Scalar::Bits {
+                    bits: layout.offset(bits as u64, i.bytes())? as u128,
+                    size,
+                })
             }
             Scalar::Ptr(ptr) => ptr.offset(i, layout).map(Scalar::Ptr),
         }
     }
 
-    pub fn ptr_wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
+    pub fn ptr_wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
         let layout = cx.data_layout();
         match self {
-            Scalar::Bits { bits, defined } => {
-                let pointer_size = layout.pointer_size.bits() as u8;
-                if defined < pointer_size {
-                    err!(ReadUndefBytes)
-                } else {
-                    Ok(Scalar::Bits {
-                        bits: layout.wrapping_signed_offset(bits as u64, i) as u128,
-                        defined: pointer_size,
-                    })
-            }
+            Scalar::Bits { bits, size } => {
+                assert_eq!(size as u64, layout.pointer_size.bytes());
+                Scalar::Bits {
+                    bits: layout.wrapping_signed_offset(bits as u64, i) as u128,
+                    size,
+                }
             }
-            Scalar::Ptr(ptr) => Ok(Scalar::Ptr(ptr.wrapping_signed_offset(i, layout))),
+            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, layout)),
         }
     }
 
-    pub fn is_null_ptr<C: HasDataLayout>(self, cx: C) -> EvalResult<'tcx, bool> {
+    pub fn is_null_ptr<C: HasDataLayout>(self, cx: C) -> bool {
         match self {
-            Scalar::Bits {
-                bits, defined,
-            } => if defined < cx.data_layout().pointer_size.bits() as u8 {
-                err!(ReadUndefBytes)
-            } else {
-                Ok(bits == 0)
+            Scalar::Bits { bits, size } =>  {
+                assert_eq!(size as u64, cx.data_layout().pointer_size.bytes());
+                bits == 0
             },
-            Scalar::Ptr(_) => Ok(false),
+            Scalar::Ptr(_) => false,
         }
     }
 
-    pub fn to_value_with_len<C: HasDataLayout>(self, len: u64, cx: C) -> Value {
-        Value::ScalarPair(self, Scalar::Bits {
-            bits: len as u128,
-            defined: cx.data_layout().pointer_size.bits() as u8,
-        })
-    }
-
-    pub fn to_value_with_vtable(self, vtable: Pointer) -> Value {
-        Value::ScalarPair(self, Scalar::Ptr(vtable))
-    }
-
     pub fn to_value(self) -> Value {
-        Value::Scalar(self)
+        Value::Scalar(ScalarMaybeUndef::Scalar(self))
     }
 }
 
@@ -199,8 +178,9 @@ fn from(ptr: Pointer) -> Self {
 pub enum Scalar {
     /// The raw bytes of a simple value.
     Bits {
-        /// The first `defined` number of bits are valid
-        defined: u8,
+        /// The first `size` bytes are the value.
+        /// Do not try to read less or more bytes that that
+        size: u8,
         bits: u128,
     },
 
@@ -210,25 +190,63 @@ pub enum Scalar {
     Ptr(Pointer),
 }
 
-impl<'tcx> Scalar {
-    pub fn undef() -> Self {
-        Scalar::Bits { bits: 0, defined: 0 }
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+pub enum ScalarMaybeUndef {
+    Scalar(Scalar),
+    Undef,
+}
+
+impl From<Scalar> for ScalarMaybeUndef {
+    fn from(s: Scalar) -> Self {
+        ScalarMaybeUndef::Scalar(s)
+    }
+}
+
+impl ScalarMaybeUndef {
+    pub fn unwrap_or_err(self) -> EvalResult<'static, Scalar> {
+        match self {
+            ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
+            ScalarMaybeUndef::Undef => err!(ReadUndefBytes),
+        }
+    }
+
+    pub fn to_value_with_len<C: HasDataLayout>(self, len: u64, cx: C) -> Value {
+        Value::ScalarPair(self, Scalar::Bits {
+            bits: len as u128,
+            size: cx.data_layout().pointer_size.bytes() as u8,
+        }.into())
     }
 
+    pub fn to_value_with_vtable(self, vtable: Pointer) -> Value {
+        Value::ScalarPair(self, Scalar::Ptr(vtable).into())
+    }
+
+    pub fn ptr_offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
+        match self {
+            ScalarMaybeUndef::Scalar(scalar) => {
+                scalar.ptr_offset(i, cx).map(ScalarMaybeUndef::Scalar)
+            },
+            ScalarMaybeUndef::Undef => Ok(ScalarMaybeUndef::Undef)
+        }
+    }
+}
+
+impl<'tcx> Scalar {
     pub fn from_bool(b: bool) -> Self {
-        // FIXME: can we make defined `1`?
-        Scalar::Bits { bits: b as u128, defined: 8 }
+        Scalar::Bits { bits: b as u128, size: 1 }
     }
 
     pub fn from_char(c: char) -> Self {
-        Scalar::Bits { bits: c as u128, defined: 32 }
+        Scalar::Bits { bits: c as u128, size: 4 }
     }
 
-    pub fn to_bits(self, size: Size) -> EvalResult<'tcx, u128> {
+    pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
         match self {
-            Scalar::Bits { .. } if size.bits() == 0 => bug!("to_bits cannot be used with zsts"),
-            Scalar::Bits { bits, defined } if size.bits() <= defined as u64 => Ok(bits),
-            Scalar::Bits { .. } => err!(ReadUndefBytes),
+            Scalar::Bits { bits, size } => {
+                assert_eq!(target_size.bytes(), size as u64);
+                assert_ne!(size, 0, "to_bits cannot be used with zsts");
+                Ok(bits)
+            }
             Scalar::Ptr(_) => err!(ReadPointerAsBytes),
         }
     }
@@ -256,8 +274,8 @@ pub fn is_ptr(self) -> bool {
 
     pub fn to_bool(self) -> EvalResult<'tcx, bool> {
         match self {
-            Scalar::Bits { bits: 0, defined: 8 } => Ok(false),
-            Scalar::Bits { bits: 1, defined: 8 } => Ok(true),
+            Scalar::Bits { bits: 0, size: 1 } => Ok(false),
+            Scalar::Bits { bits: 1, size: 1 } => Ok(true),
             _ => err!(InvalidBool),
         }
     }
index 4bfb4c96497ff6327d2d8993f45083923e2a7213..dae5709ba114a3721f86bdb41ee2fcb9ae1594e7 100644 (file)
@@ -17,7 +17,7 @@
 use hir::def_id::DefId;
 use hir::{self, HirId, InlineAsm};
 use middle::region;
-use mir::interpret::{EvalErrorKind, Scalar, Value};
+use mir::interpret::{EvalErrorKind, Scalar, Value, ScalarMaybeUndef};
 use mir::visit::MirVisitable;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
@@ -1465,10 +1465,10 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
                     .map(|&u| {
                         let mut s = String::new();
                         print_miri_value(
-                            Value::Scalar(Scalar::Bits {
+                            Scalar::Bits {
                                 bits: u,
-                                defined: size.bits() as u8,
-                            }),
+                                size: size.bytes() as u8,
+                            }.to_value(),
                             switch_ty,
                             &mut s,
                         ).unwrap();
@@ -2225,45 +2225,58 @@ pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Resul
 
 pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
     use ty::TypeVariants::*;
-    match (value, &ty.sty) {
-        (Value::Scalar(Scalar::Bits { bits: 0, .. }), &TyBool) => write!(f, "false"),
-        (Value::Scalar(Scalar::Bits { bits: 1, .. }), &TyBool) => write!(f, "true"),
-        (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F32)) => {
-            write!(f, "{}f32", Single::from_bits(bits))
-        }
-        (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F64)) => {
-            write!(f, "{}f64", Double::from_bits(bits))
-        }
-        (Value::Scalar(Scalar::Bits { bits, .. }), &TyUint(ui)) => write!(f, "{:?}{}", bits, ui),
-        (Value::Scalar(Scalar::Bits { bits, .. }), &TyInt(i)) => {
-            let bit_width = ty::tls::with(|tcx| {
-                let ty = tcx.lift_to_global(&ty).unwrap();
-                tcx.layout_of(ty::ParamEnv::empty().and(ty))
-                    .unwrap()
-                    .size
-                    .bits()
-            });
-            let shift = 128 - bit_width;
-            write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i)
-        }
-        (Value::Scalar(Scalar::Bits { bits, .. }), &TyChar) => {
-            write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap())
+    // print some primitives
+    if let Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { bits, .. })) = value {
+        match ty.sty {
+            TyBool if bits == 0 => return write!(f, "false"),
+            TyBool if bits == 1 => return write!(f, "true"),
+            TyFloat(ast::FloatTy::F32) => return write!(f, "{}f32", Single::from_bits(bits)),
+            TyFloat(ast::FloatTy::F64) => return write!(f, "{}f64", Double::from_bits(bits)),
+            TyUint(ui) => return write!(f, "{:?}{}", bits, ui),
+            TyInt(i) => {
+                let bit_width = ty::tls::with(|tcx| {
+                    let ty = tcx.lift_to_global(&ty).unwrap();
+                    tcx.layout_of(ty::ParamEnv::empty().and(ty))
+                        .unwrap()
+                        .size
+                        .bits()
+                });
+                let shift = 128 - bit_width;
+                return write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i);
+            }
+            TyChar => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
+            _ => {},
         }
-        (_, &TyFnDef(did, _)) => write!(f, "{}", item_path_str(did)),
-        (
-            Value::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: len, .. }),
-            &TyRef(_, &ty::TyS { sty: TyStr, .. }, _),
-        ) => ty::tls::with(|tcx| match tcx.alloc_map.lock().get(ptr.alloc_id) {
-            Some(interpret::AllocType::Memory(alloc)) => {
-                assert_eq!(len as usize as u128, len);
-                let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
-                let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
-                write!(f, "{:?}", s)
+    }
+    // print function definitons
+    if let TyFnDef(did, _) = ty.sty {
+        return write!(f, "{}", item_path_str(did));
+    }
+    // print string literals
+    if let Value::ScalarPair(ptr, len) = value {
+        if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = ptr {
+            if let ScalarMaybeUndef::Scalar(Scalar::Bits { bits: len, .. }) = len {
+                if let TyRef(_, &ty::TyS { sty: TyStr, .. }, _) = ty.sty {
+                    return ty::tls::with(|tcx| {
+                        let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
+                        if let Some(interpret::AllocType::Memory(alloc)) = alloc {
+                            assert_eq!(len as usize as u128, len);
+                            let slice = &alloc
+                                .bytes
+                                    [(ptr.offset.bytes() as usize)..]
+                                    [..(len as usize)];
+                            let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
+                            write!(f, "{:?}", s)
+                        } else {
+                             write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
+                        }
+                    });
+                }
             }
-            _ => write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len),
-        }),
-        _ => write!(f, "{:?}:{}", value, ty),
+        }
     }
+    // just raw dump everything else
+    write!(f, "{:?}:{}", value, ty)
 }
 
 fn item_path_str(def_id: DefId) -> String {
index 86fd825850fc54444fccd80957f2b87cdc9ad9cf..c178a9063c9acd09fa1131c52e44831ed6e6ed33 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 
 use super::*;
 
@@ -32,7 +32,7 @@
 #[derive(Clone)]
 pub struct Preorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
-    visited: BitVector<BasicBlock>,
+    visited: BitArray<BasicBlock>,
     worklist: Vec<BasicBlock>,
 }
 
@@ -42,7 +42,7 @@ pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> {
 
         Preorder {
             mir,
-            visited: BitVector::new(mir.basic_blocks().len()),
+            visited: BitArray::new(mir.basic_blocks().len()),
             worklist,
         }
     }
@@ -104,7 +104,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
 /// A Postorder traversal of this graph is `D B C A` or `D C B A`
 pub struct Postorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
-    visited: BitVector<BasicBlock>,
+    visited: BitArray<BasicBlock>,
     visit_stack: Vec<(BasicBlock, Successors<'a>)>
 }
 
@@ -112,7 +112,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
     pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
         let mut po = Postorder {
             mir,
-            visited: BitVector::new(mir.basic_blocks().len()),
+            visited: BitArray::new(mir.basic_blocks().len()),
             visit_stack: Vec::new()
         };
 
index e0532a3320bc4294673744eb8ec007d90eee6eea..3111777f4ad5a212d4ba9fd1fbf468de09c99acd 100644 (file)
 //! Contains infrastructure for configuring the compiler, including parsing
 //! command line options.
 
-pub use self::EntryFnType::*;
-pub use self::CrateType::*;
-pub use self::Passes::*;
-pub use self::DebugInfoLevel::*;
-
 use std::str::FromStr;
 
 use session::{early_error, early_warn, Session};
@@ -65,7 +60,7 @@ pub enum Sanitizer {
     Thread,
 }
 
-#[derive(Clone, Copy, PartialEq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash)]
 pub enum OptLevel {
     No,         // -O0
     Less,       // -O1
@@ -113,10 +108,10 @@ pub fn enabled(&self) -> bool {
 }
 
 #[derive(Clone, Copy, PartialEq, Hash)]
-pub enum DebugInfoLevel {
-    NoDebugInfo,
-    LimitedDebugInfo,
-    FullDebugInfo,
+pub enum DebugInfo {
+    None,
+    Limited,
+    Full,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
@@ -381,7 +376,7 @@ pub struct Options {
         // Include the debug_assertions flag into dependency tracking, since it
         // can influence whether overflow checks are done or not.
         debug_assertions: bool [TRACKED],
-        debuginfo: DebugInfoLevel [TRACKED],
+        debuginfo: DebugInfo [TRACKED],
         lint_opts: Vec<(String, lint::Level)> [TRACKED],
         lint_cap: Option<lint::Level> [TRACKED],
         describe_lints: bool [UNTRACKED],
@@ -601,37 +596,38 @@ pub fn host_triple() -> &'static str {
     (option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
 }
 
-/// Some reasonable defaults
-pub fn basic_options() -> Options {
-    Options {
-        crate_types: Vec::new(),
-        optimize: OptLevel::No,
-        debuginfo: NoDebugInfo,
-        lint_opts: Vec::new(),
-        lint_cap: None,
-        describe_lints: false,
-        output_types: OutputTypes(BTreeMap::new()),
-        search_paths: SearchPaths::new(),
-        maybe_sysroot: None,
-        target_triple: TargetTriple::from_triple(host_triple()),
-        test: false,
-        incremental: None,
-        debugging_opts: basic_debugging_options(),
-        prints: Vec::new(),
-        borrowck_mode: BorrowckMode::Ast,
-        cg: basic_codegen_options(),
-        error_format: ErrorOutputType::default(),
-        externs: Externs(BTreeMap::new()),
-        crate_name: None,
-        alt_std_name: None,
-        libs: Vec::new(),
-        unstable_features: UnstableFeatures::Disallow,
-        debug_assertions: true,
-        actually_rustdoc: false,
-        cli_forced_codegen_units: None,
-        cli_forced_thinlto_off: false,
-        remap_path_prefix: Vec::new(),
-        edition: DEFAULT_EDITION,
+impl Default for Options {
+    fn default() -> Options {
+        Options {
+            crate_types: Vec::new(),
+            optimize: OptLevel::No,
+            debuginfo: DebugInfo::None,
+            lint_opts: Vec::new(),
+            lint_cap: None,
+            describe_lints: false,
+            output_types: OutputTypes(BTreeMap::new()),
+            search_paths: SearchPaths::new(),
+            maybe_sysroot: None,
+            target_triple: TargetTriple::from_triple(host_triple()),
+            test: false,
+            incremental: None,
+            debugging_opts: basic_debugging_options(),
+            prints: Vec::new(),
+            borrowck_mode: BorrowckMode::Ast,
+            cg: basic_codegen_options(),
+            error_format: ErrorOutputType::default(),
+            externs: Externs(BTreeMap::new()),
+            crate_name: None,
+            alt_std_name: None,
+            libs: Vec::new(),
+            unstable_features: UnstableFeatures::Disallow,
+            debug_assertions: true,
+            actually_rustdoc: false,
+            cli_forced_codegen_units: None,
+            cli_forced_thinlto_off: false,
+            remap_path_prefix: Vec::new(),
+            edition: DEFAULT_EDITION,
+        }
     }
 }
 
@@ -657,6 +653,24 @@ pub fn will_create_output_file(&self) -> bool {
         !self.debugging_opts.parse_only && // The file is just being parsed
             !self.debugging_opts.ls // The file is just being queried
     }
+
+    #[inline]
+    pub fn share_generics(&self) -> bool {
+        match self.debugging_opts.share_generics {
+            Some(setting) => setting,
+            None => {
+                self.incremental.is_some() ||
+                match self.optimize {
+                    OptLevel::No   |
+                    OptLevel::Less |
+                    OptLevel::Size |
+                    OptLevel::SizeMin => true,
+                    OptLevel::Default    |
+                    OptLevel::Aggressive => false,
+                }
+            }
+        }
+    }
 }
 
 // The type of entry function, so
@@ -664,31 +678,31 @@ pub fn will_create_output_file(&self) -> bool {
 // functions
 #[derive(Copy, Clone, PartialEq)]
 pub enum EntryFnType {
-    EntryMain,
-    EntryStart,
+    Main,
+    Start,
 }
 
 #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
 pub enum CrateType {
-    CrateTypeExecutable,
-    CrateTypeDylib,
-    CrateTypeRlib,
-    CrateTypeStaticlib,
-    CrateTypeCdylib,
-    CrateTypeProcMacro,
+    Executable,
+    Dylib,
+    Rlib,
+    Staticlib,
+    Cdylib,
+    ProcMacro,
 }
 
 #[derive(Clone, Hash)]
 pub enum Passes {
-    SomePasses(Vec<String>),
-    AllPasses,
+    Some(Vec<String>),
+    All,
 }
 
 impl Passes {
     pub fn is_empty(&self) -> bool {
         match *self {
-            SomePasses(ref v) => v.is_empty(),
-            AllPasses => false,
+            Passes::Some(ref v) => v.is_empty(),
+            Passes::All => false,
         }
     }
 }
@@ -823,8 +837,7 @@ mod $mod_desc {
 
     #[allow(dead_code)]
     mod $mod_set {
-        use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto,
-                    CrossLangLto};
+        use super::{$struct_name, Passes, Sanitizer, Lto, CrossLangLto};
         use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
 
@@ -935,13 +948,13 @@ fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool {
         fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
             match v {
                 Some("all") => {
-                    *slot = AllPasses;
+                    *slot = Passes::All;
                     true
                 }
                 v => {
                     let mut passes = vec![];
                     if parse_list(&mut passes, v) {
-                        *slot = SomePasses(passes);
+                        *slot = Passes::Some(passes);
                         true
                     } else {
                         false
@@ -1104,7 +1117,7 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
          "extra data to put in each output filename"),
     codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
         "divide crate into N units to optimize in parallel"),
-    remark: Passes = (SomePasses(Vec::new()), parse_passes, [UNTRACKED],
+    remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED],
         "print remarks for these optimization passes (space separated, or \"all\")"),
     no_stack_check: bool = (false, parse_bool, [UNTRACKED],
         "the --no-stack-check flag is deprecated and does nothing"),
@@ -1367,10 +1380,14 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
         "disables the 'leak check' for subtyping; unsound, but useful for tests"),
     crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
         "inject the given attribute in the crate"),
+    self_profile: bool = (false, parse_bool, [UNTRACKED],
+          "run the self profiler"),
+    profile_json: bool = (false, parse_bool, [UNTRACKED],
+          "output a json file with profiler results"),
 }
 
 pub fn default_lib_output() -> CrateType {
-    CrateTypeRlib
+    CrateType::Rlib
 }
 
 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
@@ -1428,7 +1445,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     if sess.opts.debug_assertions {
         ret.insert((Symbol::intern("debug_assertions"), None));
     }
-    if sess.opts.crate_types.contains(&CrateTypeProcMacro) {
+    if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
         ret.insert((Symbol::intern("proc_macro"), None));
     }
     return ret;
@@ -2080,12 +2097,12 @@ pub fn build_session_options_and_crate_config(
         if cg.debuginfo.is_some() {
             early_error(error_format, "-g and -C debuginfo both provided");
         }
-        FullDebugInfo
+        DebugInfo::Full
     } else {
         match cg.debuginfo {
-            None | Some(0) => NoDebugInfo,
-            Some(1) => LimitedDebugInfo,
-            Some(2) => FullDebugInfo,
+            None | Some(0) => DebugInfo::None,
+            Some(1) => DebugInfo::Limited,
+            Some(2) => DebugInfo::Full,
             Some(arg) => {
                 early_error(
                     error_format,
@@ -2184,7 +2201,7 @@ pub fn build_session_options_and_crate_config(
         Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
     };
 
-    if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
+    if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
         early_warn(
             error_format,
             "-C remark will not show source locations without \
@@ -2273,12 +2290,12 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
         for part in unparsed_crate_type.split(',') {
             let new_part = match part {
                 "lib" => default_lib_output(),
-                "rlib" => CrateTypeRlib,
-                "staticlib" => CrateTypeStaticlib,
-                "dylib" => CrateTypeDylib,
-                "cdylib" => CrateTypeCdylib,
-                "bin" => CrateTypeExecutable,
-                "proc-macro" => CrateTypeProcMacro,
+                "rlib" => CrateType::Rlib,
+                "staticlib" => CrateType::Staticlib,
+                "dylib" => CrateType::Dylib,
+                "cdylib" => CrateType::Cdylib,
+                "bin" => CrateType::Executable,
+                "proc-macro" => CrateType::ProcMacro,
                 _ => {
                     return Err(format!("unknown crate type: `{}`", part));
                 }
@@ -2356,12 +2373,12 @@ pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]
 impl fmt::Display for CrateType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            CrateTypeExecutable => "bin".fmt(f),
-            CrateTypeDylib => "dylib".fmt(f),
-            CrateTypeRlib => "rlib".fmt(f),
-            CrateTypeStaticlib => "staticlib".fmt(f),
-            CrateTypeCdylib => "cdylib".fmt(f),
-            CrateTypeProcMacro => "proc-macro".fmt(f),
+            CrateType::Executable => "bin".fmt(f),
+            CrateType::Dylib => "dylib".fmt(f),
+            CrateType::Rlib => "rlib".fmt(f),
+            CrateType::Staticlib => "staticlib".fmt(f),
+            CrateType::Cdylib => "cdylib".fmt(f),
+            CrateType::ProcMacro => "proc-macro".fmt(f),
         }
     }
 }
@@ -2391,7 +2408,7 @@ mod dep_tracking {
     use std::hash::Hash;
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
-    use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes,
+    use super::{CrateType, DebugInfo, ErrorOutputType, Lto, OptLevel, OutputTypes,
                 Passes, Sanitizer, CrossLangLto};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
@@ -2448,7 +2465,7 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
     impl_dep_tracking_hash_via_hash!(Passes);
     impl_dep_tracking_hash_via_hash!(OptLevel);
     impl_dep_tracking_hash_via_hash!(Lto);
-    impl_dep_tracking_hash_via_hash!(DebugInfoLevel);
+    impl_dep_tracking_hash_via_hash!(DebugInfo);
     impl_dep_tracking_hash_via_hash!(UnstableFeatures);
     impl_dep_tracking_hash_via_hash!(OutputTypes);
     impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
@@ -2531,6 +2548,7 @@ mod tests {
     use syntax::symbol::Symbol;
     use syntax::edition::{Edition, DEFAULT_EDITION};
     use syntax;
+    use super::Options;
 
     fn optgroups() -> getopts::Options {
         let mut opts = getopts::Options::new();
@@ -2615,9 +2633,9 @@ fn test_can_print_warnings() {
 
     #[test]
     fn test_output_types_tracking_hash_different_paths() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
+        let mut v3 = Options::default();
 
         v1.output_types =
             OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("./some/thing")))]);
@@ -2637,8 +2655,8 @@ fn test_output_types_tracking_hash_different_paths() {
 
     #[test]
     fn test_output_types_tracking_hash_different_construction_order() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
 
         v1.output_types = OutputTypes::new(&[
             (OutputType::Exe, Some(PathBuf::from("./some/thing"))),
@@ -2658,9 +2676,9 @@ fn test_output_types_tracking_hash_different_construction_order() {
 
     #[test]
     fn test_externs_tracking_hash_different_construction_order() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
+        let mut v3 = Options::default();
 
         v1.externs = Externs::new(mk_map(vec![
             (
@@ -2707,9 +2725,9 @@ fn test_externs_tracking_hash_different_construction_order() {
 
     #[test]
     fn test_lints_tracking_hash_different_values() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
+        let mut v3 = Options::default();
 
         v1.lint_opts = vec![
             (String::from("a"), lint::Allow),
@@ -2744,8 +2762,8 @@ fn test_lints_tracking_hash_different_values() {
 
     #[test]
     fn test_lints_tracking_hash_different_construction_order() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
 
         v1.lint_opts = vec![
             (String::from("a"), lint::Allow),
@@ -2770,10 +2788,10 @@ fn test_lints_tracking_hash_different_construction_order() {
 
     #[test]
     fn test_search_paths_tracking_hash_different_order() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
-        let mut v4 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
+        let mut v3 = Options::default();
+        let mut v4 = Options::default();
 
         // Reference
         v1.search_paths
@@ -2833,10 +2851,10 @@ fn test_search_paths_tracking_hash_different_order() {
 
     #[test]
     fn test_native_libs_tracking_hash_different_values() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
-        let mut v4 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
+        let mut v3 = Options::default();
+        let mut v4 = Options::default();
 
         // Reference
         v1.libs = vec![
@@ -2883,9 +2901,9 @@ fn test_native_libs_tracking_hash_different_values() {
 
     #[test]
     fn test_native_libs_tracking_hash_different_order() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
+        let mut v1 = Options::default();
+        let mut v2 = Options::default();
+        let mut v3 = Options::default();
 
         // Reference
         v1.libs = vec![
@@ -2918,8 +2936,8 @@ fn test_native_libs_tracking_hash_different_order() {
 
     #[test]
     fn test_codegen_options_tracking_hash() {
-        let reference = super::basic_options();
-        let mut opts = super::basic_options();
+        let reference = Options::default();
+        let mut opts = Options::default();
 
         // Make sure the changing an [UNTRACKED] option leaves the hash unchanged
         opts.cg.ar = Some(String::from("abc"));
@@ -2943,7 +2961,7 @@ fn test_codegen_options_tracking_hash() {
         opts.cg.codegen_units = Some(42);
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
-        opts.cg.remark = super::SomePasses(vec![String::from("pass1"), String::from("pass2")]);
+        opts.cg.remark = super::Passes::Some(vec![String::from("pass1"), String::from("pass2")]);
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
         opts.cg.save_temps = true;
@@ -3056,8 +3074,8 @@ fn test_codegen_options_tracking_hash() {
 
     #[test]
     fn test_debugging_options_tracking_hash() {
-        let reference = super::basic_options();
-        let mut opts = super::basic_options();
+        let reference = Options::default();
+        let mut opts = Options::default();
 
         // Make sure the changing an [UNTRACKED] option leaves the hash unchanged
         opts.debugging_opts.verbose = true;
@@ -3186,7 +3204,7 @@ fn test_debugging_options_tracking_hash() {
     #[test]
     fn test_edition_parsing() {
         // test default edition
-        let options = super::basic_options();
+        let options = Options::default();
         assert!(options.edition == DEFAULT_EDITION);
 
         let matches = optgroups()
index 7b8bbbf4a10e061eb83becc03886f980e460ff5f..0173c4933f821f08e92c2387275fec9a9ad6e7a1 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
-pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
+pub use self::code_stats::{DataTypeKind, SizeKind, FieldInfo, VariantInfo};
+use self::code_stats::CodeStats;
 
 use hir::def_id::CrateNum;
 use ich::Fingerprint;
@@ -40,6 +40,7 @@
 use syntax::{ast, codemap};
 use syntax::feature_gate::AttributeType;
 use syntax_pos::{MultiSpan, Span};
+use util::profiling::SelfProfiler;
 
 use rustc_target::spec::{LinkerFlavor, PanicStrategy};
 use rustc_target::spec::{Target, TargetTriple};
@@ -133,6 +134,9 @@ pub struct Session {
     /// Used by -Z profile-queries in util::common
     pub profile_channel: Lock<Option<mpsc::Sender<ProfileQueriesMsg>>>,
 
+    /// Used by -Z self-profile
+    pub self_profiling: Lock<SelfProfiler>,
+
     /// Some measurements that are being gathered during compilation.
     pub perf_stats: PerfStats,
 
@@ -825,6 +829,21 @@ pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<PathBuf>> {
         }
     }
 
+    pub fn profiler<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+        let mut profiler = self.self_profiling.borrow_mut();
+        f(&mut profiler);
+    }
+
+    pub fn print_profiler_results(&self) {
+        let mut profiler = self.self_profiling.borrow_mut();
+        profiler.print_results(&self.opts);
+    }
+
+    pub fn save_json_results(&self) {
+        let profiler = self.self_profiling.borrow();
+        profiler.save_results(&self.opts);
+    }
+
     pub fn print_perf_stats(&self) {
         println!(
             "Total time spent computing symbol hashes:      {}",
@@ -946,7 +965,7 @@ pub fn codegen_units(&self) -> usize {
     }
 
     pub fn teach(&self, code: &DiagnosticId) -> bool {
-        self.opts.debugging_opts.teach && self.parse_sess.span_diagnostic.must_teach(code)
+        self.opts.debugging_opts.teach && self.diagnostic().must_teach(code)
     }
 
     /// Are we allowed to use features from the Rust 2018 edition?
@@ -1125,6 +1144,7 @@ pub fn build_session_(
         imported_macro_spans: OneThread::new(RefCell::new(HashMap::new())),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         ignored_attr_names: ich::compute_ignored_attr_names(),
+        self_profiling: Lock::new(SelfProfiler::new()),
         profile_channel: Lock::new(None),
         perf_stats: PerfStats {
             symbol_hash_time: Lock::new(Duration::from_secs(0)),
index 40171345f558b6b2210364c22cbb582fe1454815..35184ca6a2559cc3c3f2527db555a3addb414fc3 100644 (file)
@@ -45,7 +45,7 @@
 use mir::interpret::{GlobalId};
 
 use rustc_data_structures::sync::Lock;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use std::iter;
 use std::cmp;
 use std::fmt;
@@ -3056,7 +3056,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 } else {
                     return Err(Unimplemented);
                 };
-                let mut ty_params = BitVector::new(substs_a.types().count());
+                let mut ty_params = BitArray::new(substs_a.types().count());
                 let mut found = false;
                 for ty in field.walk() {
                     if let ty::TyParam(p) = ty.sty {
index 98568f860a4fdd62ee33a4728de581a85a31612e..0cfdea68e881c80ee4625ec52eda3175a0cb2fa6 100644 (file)
@@ -14,8 +14,8 @@
 use dep_graph::{DepNode, DepConstructor};
 use errors::DiagnosticBuilder;
 use session::Session;
-use session::config::{BorrowckMode, OutputFilenames, OptLevel};
-use session::config::CrateType::*;
+use session::config::{BorrowckMode, OutputFilenames};
+use session::config::CrateType;
 use middle;
 use hir::{TraitCandidate, HirId, ItemLocalId};
 use hir::def::{Def, Export};
@@ -1395,10 +1395,18 @@ pub fn all_pat_vars_are_implicit_refs_within_guards(self) -> bool {
     }
 
     /// If true, we should enable two-phase borrows checks. This is
-    /// done with either `-Ztwo-phase-borrows` or with
-    /// `#![feature(nll)]`.
+    /// done with either: `-Ztwo-phase-borrows`, `#![feature(nll)]`,
+    /// or by opting into an edition after 2015.
     pub fn two_phase_borrows(self) -> bool {
-        self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows
+        if self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows {
+            return true;
+        }
+
+        match self.sess.edition() {
+            Edition::Edition2015 => false,
+            Edition::Edition2018 => true,
+            _ => true,
+        }
     }
 
     /// What mode(s) of borrowck should we run? AST? MIR? both?
@@ -1461,36 +1469,18 @@ pub fn emit_end_regions(self) -> bool {
             self.use_mir_borrowck()
     }
 
-    #[inline]
-    pub fn share_generics(self) -> bool {
-        match self.sess.opts.debugging_opts.share_generics {
-            Some(setting) => setting,
-            None => {
-                self.sess.opts.incremental.is_some() ||
-                match self.sess.opts.optimize {
-                    OptLevel::No   |
-                    OptLevel::Less |
-                    OptLevel::Size |
-                    OptLevel::SizeMin => true,
-                    OptLevel::Default    |
-                    OptLevel::Aggressive => false,
-                }
-            }
-        }
-    }
-
     #[inline]
     pub fn local_crate_exports_generics(self) -> bool {
-        debug_assert!(self.share_generics());
+        debug_assert!(self.sess.opts.share_generics());
 
         self.sess.crate_types.borrow().iter().any(|crate_type| {
             match crate_type {
-                CrateTypeExecutable |
-                CrateTypeStaticlib  |
-                CrateTypeProcMacro  |
-                CrateTypeCdylib     => false,
-                CrateTypeRlib       |
-                CrateTypeDylib      => true,
+                CrateType::Executable |
+                CrateType::Staticlib  |
+                CrateType::ProcMacro  |
+                CrateType::Cdylib     => false,
+                CrateType::Rlib       |
+                CrateType::Dylib      => true,
             }
         })
     }
index fedf090b9e915a5f91779fff0dc9f560d8fc347b..d2648cad55ee9fa11dd03372af55cc510952b906 100644 (file)
@@ -21,6 +21,7 @@
 use ty::query::queries;
 use ty::query::Query;
 use ty::query::QueryCache;
+use util::profiling::ProfileCategory;
 
 use std::hash::Hash;
 use std::fmt::Debug;
@@ -33,6 +34,7 @@
 
 pub trait QueryConfig<'tcx> {
     const NAME: &'static str;
+    const CATEGORY: ProfileCategory;
 
     type Key: Eq + Hash + Clone + Debug;
     type Value: Clone + for<'a> HashStable<StableHashingContext<'a>>;
index 1b1020c9bd86dbe47d18eb8d3c466909451e6d7c..ab9bdd82e01ebf6cb97aa00f404f6810c93d571e 100644 (file)
@@ -46,6 +46,7 @@
 use ty::subst::Substs;
 use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
 use util::common::{ErrorReported};
+use util::profiling::ProfileCategory::*;
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_target::spec::PanicStrategy;
index 7a9827b50a176ec35910d2429fdd370f5ac2ec5d..0fa643d796e0e1c7a3451ad84c35b9f133bcd78e 100644 (file)
@@ -118,6 +118,11 @@ pub(super) fn try_get(
             let mut lock = cache.borrow_mut();
             if let Some(value) = lock.results.get(key) {
                 profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                tcx.sess.profiler(|p| {
+                    p.record_query(Q::CATEGORY);
+                    p.record_query_hit(Q::CATEGORY);
+                });
+
                 let result = Ok((value.value.clone(), value.index));
                 return TryGetJob::JobCompleted(result);
             }
@@ -358,10 +363,13 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
             )
         );
 
+        self.sess.profiler(|p| p.record_query(Q::CATEGORY));
+
         let job = match JobOwner::try_get(self, span, &key) {
             TryGetJob::NotYetStarted(job) => job,
             TryGetJob::JobCompleted(result) => {
                 return result.map(|(v, index)| {
+                    self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
                     self.dep_graph.read_index(index);
                     v
                 })
@@ -379,6 +387,7 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
 
         if dep_node.kind.is_anon() {
             profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+            self.sess.profiler(|p| p.start_activity(Q::CATEGORY));
 
             let res = job.start(self, |tcx| {
                 tcx.dep_graph.with_anon_task(dep_node.kind, || {
@@ -386,6 +395,7 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
                 })
             });
 
+            self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
             profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
             let ((result, dep_node_index), diagnostics) = res;
 
@@ -402,6 +412,8 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
         if !dep_node.kind.is_input() {
             if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
                 profq_msg!(self, ProfileQueriesMsg::CacheHit);
+                self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
+
                 return self.load_from_disk_and_cache_in_memory::<Q>(key,
                                                                     job,
                                                                     dep_node_index,
@@ -523,6 +535,11 @@ fn force_query_with_job<Q: QueryDescription<'gcx>>(
                 key, dep_node);
 
         profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+        self.sess.profiler(|p| {
+            p.start_activity(Q::CATEGORY);
+            p.record_query(Q::CATEGORY);
+        });
+
         let res = job.start(self, |tcx| {
             if dep_node.kind.is_eval_always() {
                 tcx.dep_graph.with_eval_always_task(dep_node,
@@ -536,6 +553,8 @@ fn force_query_with_job<Q: QueryDescription<'gcx>>(
                                         Q::compute)
             }
         });
+
+        self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
         profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
 
         let ((result, dep_node_index), diagnostics) = res;
@@ -574,7 +593,15 @@ pub(super) fn ensure_query<Q: QueryDescription<'gcx>>(self, key: Q::Key) -> () {
             // DepNodeIndex. We must invoke the query itself. The performance cost
             // this introduces should be negligible as we'll immediately hit the
             // in-memory cache, or another query down the line will.
+
+            self.sess.profiler(|p| {
+                p.start_activity(Q::CATEGORY);
+                p.record_query(Q::CATEGORY);
+            });
+
             let _ = self.get_query::<Q>(DUMMY_SP, key);
+
+            self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
         }
     }
 
@@ -655,6 +682,7 @@ macro_rules! define_queries_inner {
             rustc_data_structures::stable_hasher::StableHasher,
             ich::StableHashingContext
         };
+        use util::profiling::ProfileCategory;
 
         define_queries_struct! {
             tcx: $tcx,
@@ -768,6 +796,7 @@ pub fn $name<F: FnOnce() -> R, R>(f: F) -> R {
             type Value = $V;
 
             const NAME: &'static str = stringify!($name);
+            const CATEGORY: ProfileCategory = $category;
         }
 
         impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> {
index dd38188824338f7a1a5bb648c701f7dd5865696a..96b4edce86b30f5603b33af3f259b4bd62ce213e 100644 (file)
@@ -1887,22 +1887,13 @@ pub fn from_const_value(
         })
     }
 
-    #[inline]
-    pub fn from_byval_value(
-        tcx: TyCtxt<'_, '_, 'tcx>,
-        val: Value,
-        ty: Ty<'tcx>,
-    ) -> &'tcx Self {
-        Self::from_const_value(tcx, ConstValue::from_byval_value(val), ty)
-    }
-
     #[inline]
     pub fn from_scalar(
         tcx: TyCtxt<'_, '_, 'tcx>,
         val: Scalar,
         ty: Ty<'tcx>,
     ) -> &'tcx Self {
-        Self::from_const_value(tcx, ConstValue::from_scalar(val), ty)
+        Self::from_const_value(tcx, ConstValue::Scalar(val), ty)
     }
 
     #[inline]
@@ -1918,12 +1909,12 @@ pub fn from_bits(
         let shift = 128 - size.bits();
         let truncated = (bits << shift) >> shift;
         assert_eq!(truncated, bits, "from_bits called with untruncated value");
-        Self::from_scalar(tcx, Scalar::Bits { bits, defined: size.bits() as u8 }, ty.value)
+        Self::from_scalar(tcx, Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value)
     }
 
     #[inline]
     pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
-        Self::from_scalar(tcx, Scalar::undef(), ty)
+        Self::from_scalar(tcx, Scalar::Bits { bits: 0, size: 0 }, ty)
     }
 
     #[inline]
@@ -1960,11 +1951,6 @@ pub fn to_byval_value(&self) -> Option<Value> {
         self.val.to_byval_value()
     }
 
-    #[inline]
-    pub fn to_scalar(&self) -> Option<Scalar> {
-        self.val.to_scalar()
-    }
-
     #[inline]
     pub fn assert_bits(
         &self,
diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs
new file mode 100644 (file)
index 0000000..447b75e
--- /dev/null
@@ -0,0 +1,248 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use session::config::Options;
+
+use std::fs;
+use std::io::{self, StdoutLock, Write};
+use std::time::Instant;
+
+macro_rules! define_categories {
+    ($($name:ident,)*) => {
+        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
+        pub enum ProfileCategory {
+            $($name),*
+        }
+
+        #[allow(bad_style)]
+        struct Categories<T> {
+            $($name: T),*
+        }
+
+        impl<T: Default> Categories<T> {
+            fn new() -> Categories<T> {
+                Categories {
+                    $($name: T::default()),*
+                }
+            }
+        }
+
+        impl<T> Categories<T> {
+            fn get(&self, category: ProfileCategory) -> &T {
+                match category {
+                    $(ProfileCategory::$name => &self.$name),*
+                }
+            }
+
+            fn set(&mut self, category: ProfileCategory, value: T) {
+                match category {
+                    $(ProfileCategory::$name => self.$name = value),*
+                }
+            }
+        }
+
+        struct CategoryData {
+            times: Categories<u64>,
+            query_counts: Categories<(u64, u64)>,
+        }
+
+        impl CategoryData {
+            fn new() -> CategoryData {
+                CategoryData {
+                    times: Categories::new(),
+                    query_counts: Categories::new(),
+                }
+            }
+
+            fn print(&self, lock: &mut StdoutLock) {
+                writeln!(lock, "| Phase            | Time (ms)      | Queries        | Hits (%) |")
+                    .unwrap();
+                writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
+                    .unwrap();
+
+                $(
+                    let (hits, total) = self.query_counts.$name;
+                    let (hits, total) = if total > 0 {
+                        (format!("{:.2}",
+                        (((hits as f32) / (total as f32)) * 100.0)), total.to_string())
+                    } else {
+                        ("".into(), "".into())
+                    };
+
+                    writeln!(
+                        lock,
+                        "| {0: <16} | {1: <14} | {2: <14} | {3: <8} |",
+                        stringify!($name),
+                        self.times.$name / 1_000_000,
+                        total,
+                        hits
+                    ).unwrap();
+                )*
+            }
+
+            fn json(&self) -> String {
+                let mut json = String::from("[");
+
+                $(
+                    let (hits, total) = self.query_counts.$name;
+
+                    json.push_str(&format!(
+                        "{{ \"category\": {}, \"time_ms\": {},
+                            \"query_count\": {}, \"query_hits\": {} }}",
+                        stringify!($name),
+                        self.times.$name / 1_000_000,
+                        total,
+                        format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0))
+                    ));
+                )*
+
+                json.push(']');
+
+                json
+            }
+        }
+    }
+}
+
+define_categories! {
+    Parsing,
+    Expansion,
+    TypeChecking,
+    BorrowChecking,
+    Codegen,
+    Linking,
+    Other,
+}
+
+pub struct SelfProfiler {
+    timer_stack: Vec<ProfileCategory>,
+    data: CategoryData,
+    current_timer: Instant,
+}
+
+impl SelfProfiler {
+    pub fn new() -> SelfProfiler {
+        let mut profiler = SelfProfiler {
+            timer_stack: Vec::new(),
+            data: CategoryData::new(),
+            current_timer: Instant::now(),
+        };
+
+        profiler.start_activity(ProfileCategory::Other);
+
+        profiler
+    }
+
+    pub fn start_activity(&mut self, category: ProfileCategory) {
+        match self.timer_stack.last().cloned() {
+            None => {
+                self.current_timer = Instant::now();
+            },
+            Some(current_category) if current_category == category => {
+                //since the current category is the same as the new activity's category,
+                //we don't need to do anything with the timer, we just need to push it on the stack
+            }
+            Some(current_category) => {
+                let elapsed = self.stop_timer();
+
+                //record the current category's time
+                let new_time = self.data.times.get(current_category) + elapsed;
+                self.data.times.set(current_category, new_time);
+            }
+        }
+
+        //push the new category
+        self.timer_stack.push(category);
+    }
+
+    pub fn record_query(&mut self, category: ProfileCategory) {
+        let (hits, total) = *self.data.query_counts.get(category);
+        self.data.query_counts.set(category, (hits, total + 1));
+    }
+
+    pub fn record_query_hit(&mut self, category: ProfileCategory) {
+        let (hits, total) = *self.data.query_counts.get(category);
+        self.data.query_counts.set(category, (hits + 1, total));
+    }
+
+    pub fn end_activity(&mut self, category: ProfileCategory) {
+        match self.timer_stack.pop() {
+            None => bug!("end_activity() was called but there was no running activity"),
+            Some(c) =>
+                assert!(
+                    c == category,
+                    "end_activity() was called but a different activity was running"),
+        }
+
+        //check if the new running timer is in the same category as this one
+        //if it is, we don't need to do anything
+        if let Some(c) = self.timer_stack.last() {
+            if *c == category {
+                return;
+            }
+        }
+
+        //the new timer is different than the previous,
+        //so record the elapsed time and start a new timer
+        let elapsed = self.stop_timer();
+        let new_time = self.data.times.get(category) + elapsed;
+        self.data.times.set(category, new_time);
+    }
+
+    fn stop_timer(&mut self) -> u64 {
+        let elapsed = self.current_timer.elapsed();
+
+        self.current_timer = Instant::now();
+
+        (elapsed.as_secs() * 1_000_000_000) + (elapsed.subsec_nanos() as u64)
+    }
+
+    pub fn print_results(&mut self, opts: &Options) {
+        self.end_activity(ProfileCategory::Other);
+
+        assert!(
+            self.timer_stack.is_empty(),
+            "there were timers running when print_results() was called");
+
+        let out = io::stdout();
+        let mut lock = out.lock();
+
+        let crate_name =
+            opts.crate_name
+            .as_ref()
+            .map(|n| format!(" for {}", n))
+            .unwrap_or_default();
+
+        writeln!(lock, "Self profiling results{}:", crate_name).unwrap();
+        writeln!(lock).unwrap();
+
+        self.data.print(&mut lock);
+
+        writeln!(lock).unwrap();
+        writeln!(lock, "Optimization level: {:?}", opts.optimize).unwrap();
+
+        let incremental = if opts.incremental.is_some() { "on" } else { "off" };
+        writeln!(lock, "Incremental: {}", incremental).unwrap();
+    }
+
+    pub fn save_results(&self, opts: &Options) {
+        let category_data = self.data.json();
+        let compilation_options =
+            format!("{{ \"optimization_level\": \"{:?}\", \"incremental\": {} }}",
+                    opts.optimize,
+                    if opts.incremental.is_some() { "true" } else { "false" });
+
+        let json = format!("{{ \"category_data\": {}, \"compilation_options\": {} }}",
+                        category_data,
+                        compilation_options);
+
+        fs::write("self_profiler_results.json", json).unwrap();
+    }
+}
index f1a6e9913d6bdfc0cc81161af8a3912c32d2b2c1..44982eee86b3cec02e2e4163b950233c8d8892fa 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef, AttributePlace};
+use llvm::{self, AttributePlace};
 use base;
 use builder::{Builder, MemFlags};
 use common::{ty_fn_sig, C_usize};
@@ -17,6 +17,7 @@
 use mir::operand::OperandValue;
 use type_::Type;
 use type_of::{LayoutLlvmExt, PointerKind};
+use value::Value;
 
 use rustc_target::abi::{LayoutOf, Size, TyLayout};
 use rustc::ty::{self, Ty};
@@ -46,12 +47,12 @@ fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
 }
 
 pub trait ArgAttributesExt {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef);
-    fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef);
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value);
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value);
 }
 
 impl ArgAttributesExt for ArgAttributes {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -76,7 +77,7 @@ fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
         }
     }
 
-    fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -103,11 +104,11 @@ fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
 }
 
 pub trait LlvmType {
-    fn llvm_type(&self, cx: &CodegenCx) -> Type;
+    fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type;
 }
 
 impl LlvmType for Reg {
-    fn llvm_type(&self, cx: &CodegenCx) -> Type {
+    fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         match self.kind {
             RegKind::Integer => Type::ix(cx, self.size.bits()),
             RegKind::Float => {
@@ -118,14 +119,14 @@ fn llvm_type(&self, cx: &CodegenCx) -> Type {
                 }
             }
             RegKind::Vector => {
-                Type::vector(&Type::i8(cx), self.size.bytes())
+                Type::vector(Type::i8(cx), self.size.bytes())
             }
         }
     }
 }
 
 impl LlvmType for CastTarget {
-    fn llvm_type(&self, cx: &CodegenCx) -> Type {
+    fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         let rest_ll_unit = self.rest.unit.llvm_type(cx);
         let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 {
             (0, 0)
@@ -142,7 +143,7 @@ fn llvm_type(&self, cx: &CodegenCx) -> Type {
 
             // Simplify to array when all chunks are the same size and type
             if rem_bytes == 0 {
-                return Type::array(&rest_ll_unit, rest_count);
+                return Type::array(rest_ll_unit, rest_count);
             }
         }
 
@@ -164,16 +165,16 @@ fn llvm_type(&self, cx: &CodegenCx) -> Type {
     }
 }
 
-pub trait ArgTypeExt<'a, 'tcx> {
-    fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
-    fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>);
-    fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>);
+pub trait ArgTypeExt<'ll, 'tcx> {
+    fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
+    fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>);
+    fn store_fn_arg(&self, bx: &Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>);
 }
 
-impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
+impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
     /// Get the LLVM type for a place of the original Rust type of
     /// this argument/return, i.e. the result of `type_of::type_of`.
-    fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         self.layout.llvm_type(cx)
     }
 
@@ -181,7 +182,7 @@ fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
     /// place for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
     /// or results of call/invoke instructions into their destinations.
-    fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
+    fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>) {
         if self.is_ignore() {
             return;
         }
@@ -234,7 +235,7 @@ fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
         }
     }
 
-    fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
+    fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>) {
         let mut next = || {
             let val = llvm::get_param(bx.llfn(), *idx as c_uint);
             *idx += 1;
@@ -252,32 +253,32 @@ fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'t
     }
 }
 
-pub trait FnTypeExt<'a, 'tcx> {
-    fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+pub trait FnTypeExt<'tcx> {
+    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
                    -> Self;
-    fn new(cx: &CodegenCx<'a, 'tcx>,
+    fn new(cx: &CodegenCx<'ll, 'tcx>,
            sig: ty::FnSig<'tcx>,
            extra_args: &[Ty<'tcx>]) -> Self;
-    fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
+    fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
                   sig: ty::FnSig<'tcx>,
                   extra_args: &[Ty<'tcx>]) -> Self;
     fn new_internal(
-        cx: &CodegenCx<'a, 'tcx>,
+        cx: &CodegenCx<'ll, 'tcx>,
         sig: ty::FnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
     ) -> Self;
     fn adjust_for_abi(&mut self,
-                      cx: &CodegenCx<'a, 'tcx>,
+                      cx: &CodegenCx<'ll, 'tcx>,
                       abi: Abi);
-    fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
-    fn apply_attrs_llfn(&self, llfn: ValueRef);
-    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef);
+    fn apply_attrs_llfn(&self, llfn: &'ll Value);
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
 }
 
-impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
-    fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
+    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
                        -> Self {
         let fn_ty = instance.ty(cx.tcx);
         let sig = ty_fn_sig(cx, fn_ty);
@@ -285,7 +286,7 @@ fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
         FnType::new(cx, sig, &[])
     }
 
-    fn new(cx: &CodegenCx<'a, 'tcx>,
+    fn new(cx: &CodegenCx<'ll, 'tcx>,
                sig: ty::FnSig<'tcx>,
                extra_args: &[Ty<'tcx>]) -> Self {
         FnType::new_internal(cx, sig, extra_args, |ty, _| {
@@ -293,7 +294,7 @@ fn new(cx: &CodegenCx<'a, 'tcx>,
         })
     }
 
-    fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
+    fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
                       sig: ty::FnSig<'tcx>,
                       extra_args: &[Ty<'tcx>]) -> Self {
         FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
@@ -316,7 +317,7 @@ fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
     }
 
     fn new_internal(
-        cx: &CodegenCx<'a, 'tcx>,
+        cx: &CodegenCx<'ll, 'tcx>,
         sig: ty::FnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
@@ -497,7 +498,7 @@ fn new_internal(
     }
 
     fn adjust_for_abi(&mut self,
-                      cx: &CodegenCx<'a, 'tcx>,
+                      cx: &CodegenCx<'ll, 'tcx>,
                       abi: Abi) {
         if abi == Abi::Unadjusted { return }
 
@@ -564,7 +565,7 @@ fn adjust_for_abi(&mut self,
         }
     }
 
-    fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         let args_capacity: usize = self.args.iter().map(|arg|
             if arg.pad.is_some() { 1 } else { 0 } +
             if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
@@ -606,9 +607,9 @@ fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         }
 
         if self.variadic {
-            Type::variadic_func(&llargument_tys, &llreturn_ty)
+            Type::variadic_func(&llargument_tys, llreturn_ty)
         } else {
-            Type::func(&llargument_tys, &llreturn_ty)
+            Type::func(&llargument_tys, llreturn_ty)
         }
     }
 
@@ -629,7 +630,7 @@ fn llvm_cconv(&self) -> llvm::CallConv {
         }
     }
 
-    fn apply_attrs_llfn(&self, llfn: ValueRef) {
+    fn apply_attrs_llfn(&self, llfn: &'ll Value) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
@@ -659,7 +660,7 @@ fn apply_attrs_llfn(&self, llfn: ValueRef) {
         }
     }
 
-    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) {
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
index eeb02e948f1ccbd7ec4471091e537e3ab5a607d7..2d401da958b13fa6465af1612a64b95774198862 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use std::ffi::CString;
-use std::ptr;
 
 use attributes;
 use libc::c_uint;
@@ -21,8 +20,8 @@
 use llvm::{self, False, True};
 
 pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
-    let llcx = mods.llcx;
-    let llmod = mods.llmod;
+    let llcx = &*mods.llcx;
+    let llmod = mods.llmod();
     let usize = match &tcx.sess.target.target.target_pointer_width[..] {
         "16" => llvm::LLVMInt16TypeInContext(llcx),
         "32" => llvm::LLVMInt32TypeInContext(llcx),
@@ -90,7 +89,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind
                                           callee,
                                           args.as_ptr(),
                                           args.len() as c_uint,
-                                          ptr::null_mut(),
+                                          None,
                                           "\0".as_ptr() as *const _);
         llvm::LLVMSetTailCall(ret, True);
         if output.is_some() {
index 82f068106ff71839265c47f28a41a48272f05832..5d27f8eab3ecea095fc275fca1cb473ede236181 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef};
+use llvm;
 use common::*;
 use type_::Type;
 use type_of::LayoutLlvmExt;
 use builder::Builder;
+use value::Value;
 
 use rustc::hir;
 
 use libc::{c_uint, c_char};
 
 // Take an inline assembly expression and splat it out via LLVM
-pub fn codegen_inline_asm<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
+pub fn codegen_inline_asm(
+    bx: &Builder<'a, 'll, 'tcx>,
     ia: &hir::InlineAsm,
-    outputs: Vec<PlaceRef<'tcx>>,
-    mut inputs: Vec<ValueRef>
+    outputs: Vec<PlaceRef<'ll, 'tcx>>,
+    mut inputs: Vec<&'ll Value>
 ) {
     let mut ext_constraints = vec![];
     let mut output_types = vec![];
@@ -111,7 +112,7 @@ pub fn codegen_inline_asm<'a, 'tcx>(
         let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx,
             key.as_ptr() as *const c_char, key.len() as c_uint);
 
-        let val: llvm::ValueRef = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
+        let val: &'ll Value = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
 
         llvm::LLVMSetMetadata(r, kind,
             llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
index 3b5f927d52f005e801e3c3deb06790a0f6bd8d5c..c52f894410899bf26578f0a214fcfb48a08e32f6 100644 (file)
 use rustc_target::spec::PanicStrategy;
 
 use attributes;
-use llvm::{self, Attribute, ValueRef};
+use llvm::{self, Attribute};
 use llvm::AttributePlace::Function;
 use llvm_util;
 pub use syntax::attr::{self, InlineAttr};
+
 use context::CodegenCx;
+use value::Value;
 
 /// Mark LLVM function to use provided inline heuristic.
 #[inline]
-pub fn inline(val: ValueRef, inline: InlineAttr) {
+pub fn inline(val: &'ll Value, inline: InlineAttr) {
     use self::InlineAttr::*;
     match inline {
         Hint   => Attribute::InlineHint.apply_llfn(Function, val),
@@ -46,30 +48,30 @@ pub fn inline(val: ValueRef, inline: InlineAttr) {
 
 /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
 #[inline]
-pub fn emit_uwtable(val: ValueRef, emit: bool) {
+pub fn emit_uwtable(val: &'ll Value, emit: bool) {
     Attribute::UWTable.toggle_llfn(Function, val, emit);
 }
 
 /// Tell LLVM whether the function can or cannot unwind.
 #[inline]
-pub fn unwind(val: ValueRef, can_unwind: bool) {
+pub fn unwind(val: &'ll Value, can_unwind: bool) {
     Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind);
 }
 
 /// Tell LLVM whether it should optimize function for size.
 #[inline]
 #[allow(dead_code)] // possibly useful function
-pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
+pub fn set_optimize_for_size(val: &'ll Value, optimize: bool) {
     Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize);
 }
 
 /// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue.
 #[inline]
-pub fn naked(val: ValueRef, is_naked: bool) {
+pub fn naked(val: &'ll Value, is_naked: bool) {
     Attribute::Naked.toggle_llfn(Function, val, is_naked);
 }
 
-pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) {
+pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     if cx.sess().must_not_eliminate_frame_pointers() {
         llvm::AddFunctionAttrStringValue(
             llfn, llvm::AttributePlace::Function,
@@ -77,7 +79,7 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) {
     }
 }
 
-pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
+pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     // Only use stack probes if the target specification indicates that we
     // should be using stack probes
     if !cx.sess().target.target.options.stack_probes {
@@ -123,7 +125,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
 
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
-pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
+pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) {
     let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(id);
 
     inline(llfn, codegen_fn_attrs.inline);
index b99835cb5c64932876420447f871020f0ce4bdd9..af9efc6d7c4173f905254795be1d431a9255258e 100644 (file)
@@ -226,10 +226,13 @@ fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
     }
 
     fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
-        let mut archives = Vec::new();
+        let removals = mem::replace(&mut self.removals, Vec::new());
+        let mut additions = mem::replace(&mut self.additions, Vec::new());
         let mut strings = Vec::new();
         let mut members = Vec::new();
-        let removals = mem::replace(&mut self.removals, Vec::new());
+
+        let dst = CString::new(self.config.dst.to_str().unwrap())?;
+        let should_update_symbols = self.should_update_symbols;
 
         unsafe {
             if let Some(archive) = self.src_archive() {
@@ -246,22 +249,22 @@ fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
                     let name = CString::new(child_name)?;
                     members.push(llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                 name.as_ptr(),
-                                                                child.raw()));
+                                                                Some(child.raw)));
                     strings.push(name);
                 }
             }
-            for addition in mem::replace(&mut self.additions, Vec::new()) {
+            for addition in &mut additions {
                 match addition {
                     Addition::File { path, name_in_archive } => {
                         let path = CString::new(path.to_str().unwrap())?;
-                        let name = CString::new(name_in_archive)?;
+                        let name = CString::new(name_in_archive.clone())?;
                         members.push(llvm::LLVMRustArchiveMemberNew(path.as_ptr(),
                                                                     name.as_ptr(),
-                                                                    ptr::null_mut()));
+                                                                    None));
                         strings.push(path);
                         strings.push(name);
                     }
-                    Addition::Archive { archive, mut skip } => {
+                    Addition::Archive { archive, skip } => {
                         for child in archive.iter() {
                             let child = child.map_err(string_to_io_error)?;
                             if !is_relevant_child(&child) {
@@ -284,21 +287,18 @@ fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
                             let name = CString::new(child_name)?;
                             let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                    name.as_ptr(),
-                                                                   child.raw());
+                                                                   Some(child.raw));
                             members.push(m);
                             strings.push(name);
                         }
-                        archives.push(archive);
                     }
                 }
             }
 
-            let dst = self.config.dst.to_str().unwrap().as_bytes();
-            let dst = CString::new(dst)?;
             let r = llvm::LLVMRustWriteArchive(dst.as_ptr(),
                                                members.len() as libc::size_t,
-                                               members.as_ptr(),
-                                               self.should_update_symbols,
+                                               members.as_ptr() as *const &_,
+                                               should_update_symbols,
                                                kind);
             let ret = if r.into_result().is_err() {
                 let err = llvm::LLVMRustGetLastError();
index 845a66c6e4436efaae724d841122619ab335dc20..108734b67d3b837a92efb20e85e24d56d719a3ee 100644 (file)
@@ -17,7 +17,7 @@
 use super::rpath::RPathConfig;
 use super::rpath;
 use metadata::METADATA_FILENAME;
-use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest};
+use rustc::session::config::{self, DebugInfo, OutputFilenames, OutputType, PrintRequest};
 use rustc::session::config::{RUST_CGU_EXT, Lto};
 use rustc::session::filesearch;
 use rustc::session::search_paths::PathKind;
@@ -151,7 +151,7 @@ pub(crate) fn link_binary(sess: &Session,
         let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
         if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) &&
            !output_metadata &&
-           crate_type == config::CrateTypeExecutable {
+           crate_type == config::CrateType::Executable {
             continue;
         }
 
@@ -200,7 +200,7 @@ pub(crate) fn link_binary(sess: &Session,
 /// split-dwarf like schemes.
 fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
     // If the objects don't have debuginfo there's nothing to preserve.
-    if sess.opts.debuginfo == NoDebugInfo {
+    if sess.opts.debuginfo == DebugInfo::None {
         return false
     }
 
@@ -208,7 +208,7 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
     // the objects as they're losslessly contained inside the archives.
     let output_linked = sess.crate_types.borrow()
         .iter()
-        .any(|x| *x != config::CrateTypeRlib && *x != config::CrateTypeStaticlib);
+        .any(|x| *x != config::CrateType::Rlib && *x != config::CrateType::Staticlib);
     if !output_linked {
         return false
     }
@@ -255,10 +255,10 @@ pub(crate) fn each_linked_rlib(sess: &Session,
                                f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> {
     let crates = info.used_crates_static.iter();
     let fmts = sess.dependency_formats.borrow();
-    let fmts = fmts.get(&config::CrateTypeExecutable)
-                   .or_else(|| fmts.get(&config::CrateTypeStaticlib))
-                   .or_else(|| fmts.get(&config::CrateTypeCdylib))
-                   .or_else(|| fmts.get(&config::CrateTypeProcMacro));
+    let fmts = fmts.get(&config::CrateType::Executable)
+                   .or_else(|| fmts.get(&config::CrateType::Staticlib))
+                   .or_else(|| fmts.get(&config::CrateType::Cdylib))
+                   .or_else(|| fmts.get(&config::CrateType::ProcMacro));
     let fmts = match fmts {
         Some(f) => f,
         None => return Err("could not find formats for rlibs".to_string())
@@ -344,14 +344,14 @@ fn link_binary_output(sess: &Session,
     if outputs.outputs.should_codegen() {
         let out_filename = out_filename(sess, crate_type, outputs, crate_name);
         match crate_type {
-            config::CrateTypeRlib => {
+            config::CrateType::Rlib => {
                 link_rlib(sess,
                           codegen_results,
                           RlibFlavor::Normal,
                           &out_filename,
                           &tmpdir).build();
             }
-            config::CrateTypeStaticlib => {
+            config::CrateType::Staticlib => {
                 link_staticlib(sess, codegen_results, &out_filename, &tmpdir);
             }
             _ => {
@@ -644,7 +644,7 @@ fn link_natively(sess: &Session,
     }
     cmd.args(&sess.opts.debugging_opts.pre_link_arg);
 
-    let pre_link_objects = if crate_type == config::CrateTypeExecutable {
+    let pre_link_objects = if crate_type == config::CrateType::Executable {
         &sess.target.target.options.pre_link_objects_exe
     } else {
         &sess.target.target.options.pre_link_objects_dll
@@ -653,7 +653,7 @@ fn link_natively(sess: &Session,
         cmd.arg(root.join(obj));
     }
 
-    if crate_type == config::CrateTypeExecutable && sess.crt_static() {
+    if crate_type == config::CrateType::Executable && sess.crt_static() {
         for obj in &sess.target.target.options.pre_link_objects_exe_crt {
             cmd.arg(root.join(obj));
         }
@@ -834,7 +834,7 @@ fn escape_string(s: &[u8]) -> String {
     // the symbols. Note, though, that if the object files are being preserved
     // for their debug information there's no need for us to run dsymutil.
     if sess.target.target.options.is_like_osx &&
-        sess.opts.debuginfo != NoDebugInfo &&
+        sess.opts.debuginfo != DebugInfo::None &&
         !preserve_objects_for_their_debuginfo(sess)
     {
         match Command::new("dsymutil").arg(out_filename).output() {
@@ -1013,7 +1013,7 @@ fn link_args(cmd: &mut dyn Linker,
     }
     cmd.output_filename(out_filename);
 
-    if crate_type == config::CrateTypeExecutable &&
+    if crate_type == config::CrateType::Executable &&
        sess.target.target.options.is_like_windows {
         if let Some(ref s) = codegen_results.windows_subsystem {
             cmd.subsystem(s);
@@ -1022,7 +1022,7 @@ fn link_args(cmd: &mut dyn Linker,
 
     // If we're building a dynamic library then some platforms need to make sure
     // that all symbols are exported correctly from the dynamic library.
-    if crate_type != config::CrateTypeExecutable ||
+    if crate_type != config::CrateType::Executable ||
        sess.target.target.options.is_like_emscripten {
         cmd.export_symbols(tmpdir, crate_type);
     }
@@ -1030,8 +1030,8 @@ fn link_args(cmd: &mut dyn Linker,
     // When linking a dynamic library, we put the metadata into a section of the
     // executable. This metadata is in a separate object file from the main
     // object file, so we link that in here.
-    if crate_type == config::CrateTypeDylib ||
-       crate_type == config::CrateTypeProcMacro {
+    if crate_type == config::CrateType::Dylib ||
+       crate_type == config::CrateType::ProcMacro {
         if let Some(obj) = codegen_results.metadata_module.object.as_ref() {
             cmd.add_object(obj);
         }
@@ -1047,13 +1047,13 @@ fn link_args(cmd: &mut dyn Linker,
     // Try to strip as much out of the generated object by removing unused
     // sections if possible. See more comments in linker.rs
     if !sess.opts.cg.link_dead_code {
-        let keep_metadata = crate_type == config::CrateTypeDylib;
+        let keep_metadata = crate_type == config::CrateType::Dylib;
         cmd.gc_sections(keep_metadata);
     }
 
     let used_link_args = &codegen_results.crate_info.link_args;
 
-    if crate_type == config::CrateTypeExecutable {
+    if crate_type == config::CrateType::Executable {
         let mut position_independent_executable = false;
 
         if t.options.position_independent_executables {
@@ -1145,10 +1145,10 @@ fn link_args(cmd: &mut dyn Linker,
     add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
 
     // Tell the linker what we're doing.
-    if crate_type != config::CrateTypeExecutable {
+    if crate_type != config::CrateType::Executable {
         cmd.build_dylib(out_filename);
     }
-    if crate_type == config::CrateTypeExecutable && sess.crt_static() {
+    if crate_type == config::CrateType::Executable && sess.crt_static() {
         cmd.build_static_executable();
     }
 
@@ -1448,7 +1448,7 @@ fn add_static_crate(cmd: &mut dyn Linker,
 
         if (!is_full_lto_enabled(sess) ||
             ignored_for_lto(sess, &codegen_results.crate_info, cnum)) &&
-           crate_type != config::CrateTypeDylib &&
+           crate_type != config::CrateType::Dylib &&
            !skip_native {
             cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
             return
@@ -1524,7 +1524,7 @@ fn looks_like_rust(s: &str) -> bool {
             // Note, though, that we don't want to include the whole of a
             // compiler-builtins crate (e.g. compiler-rt) because it'll get
             // repeatedly linked anyway.
-            if crate_type == config::CrateTypeDylib &&
+            if crate_type == config::CrateType::Dylib &&
                 codegen_results.crate_info.compiler_builtins != Some(cnum) {
                 cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
             } else {
index 5f2f3733ec7f0df434ed9f2e01ea3e5912ea0528..e0a30ef5dbc9abe10befecbda24285ef84a394fd 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
 use rustc::middle::dependency_format::Linkage;
 use rustc::session::Session;
-use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel,
+use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
                              CrossLangLto};
 use rustc::ty::TyCtxt;
 use rustc_target::spec::{LinkerFlavor, LldFlavor};
@@ -338,7 +338,7 @@ fn pgo_gen(&mut self) {
 
     fn debuginfo(&mut self) {
         match self.sess.opts.debuginfo {
-            DebugInfoLevel::NoDebugInfo => {
+            DebugInfo::None => {
                 // If we are building without debuginfo enabled and we were called with
                 // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
                 // found when linking to get rid of symbols from libstd.
@@ -387,8 +387,8 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
         // exported symbols to ensure we don't expose any more. The object files
         // have far more public symbols than we actually want to export, so we
         // hide them all here.
-        if crate_type == CrateType::CrateTypeDylib ||
-           crate_type == CrateType::CrateTypeProcMacro {
+        if crate_type == CrateType::Dylib ||
+           crate_type == CrateType::ProcMacro {
             return
         }
 
@@ -826,9 +826,9 @@ fn pgo_gen(&mut self) {
     fn debuginfo(&mut self) {
         // Preserve names or generate source maps depending on debug info
         self.cmd.arg(match self.sess.opts.debuginfo {
-            DebugInfoLevel::NoDebugInfo => "-g0",
-            DebugInfoLevel::LimitedDebugInfo => "-g3",
-            DebugInfoLevel::FullDebugInfo => "-g4"
+            DebugInfo::None => "-g0",
+            DebugInfo::Limited => "-g3",
+            DebugInfo::Full => "-g4"
         });
     }
 
@@ -1006,6 +1006,18 @@ fn optimize(&mut self) {
             OptLevel::Size => "-O2",
             OptLevel::SizeMin => "-O2"
         });
+        match self.sess.opts.optimize {
+            OptLevel::No => (),
+            OptLevel::Less |
+            OptLevel::Default |
+            OptLevel::Aggressive |
+            OptLevel::Size |
+            OptLevel::SizeMin => {
+                // LLD generates incorrect debugging information when
+                // optimization is applied: strip debug sections.
+                self.cmd.arg("--strip-debug");
+            }
+        }
     }
 
     fn pgo_gen(&mut self) {
index 93cb9eb9767657ed32bc876b828dd17bfe8ac06c..098676c95a2892472c731c6db1098d09e45317e0 100644 (file)
 use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION};
 use back::symbol_export;
 use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext};
-use back::write;
+use back::write::{self, DiagnosticHandlers};
 use errors::{FatalError, Handler};
 use llvm::archive_ro::ArchiveRO;
-use llvm::{ModuleRef, TargetMachineRef, True, False};
+use llvm::{True, False};
 use llvm;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::exported_symbols::SymbolExportLevel;
 
 pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
     match crate_type {
-        config::CrateTypeExecutable |
-        config::CrateTypeStaticlib  |
-        config::CrateTypeCdylib     => true,
+        config::CrateType::Executable |
+        config::CrateType::Staticlib  |
+        config::CrateType::Cdylib     => true,
 
-        config::CrateTypeDylib     |
-        config::CrateTypeRlib      |
-        config::CrateTypeProcMacro => false,
+        config::CrateType::Dylib     |
+        config::CrateType::Rlib      |
+        config::CrateType::ProcMacro => false,
     }
 }
 
@@ -73,11 +73,13 @@ pub(crate) unsafe fn optimize(&mut self,
         match *self {
             LtoModuleCodegen::Fat { ref mut module, .. } => {
                 let module = module.take().unwrap();
-                let config = cgcx.config(module.kind);
-                let llmod = module.llvm().unwrap().llmod;
-                let tm = module.llvm().unwrap().tm;
-                run_pass_manager(cgcx, tm, llmod, config, false);
-                timeline.record("fat-done");
+                {
+                    let config = cgcx.config(module.kind);
+                    let llmod = module.llvm().unwrap().llmod();
+                    let tm = &*module.llvm().unwrap().tm;
+                    run_pass_manager(cgcx, tm, llmod, config, false);
+                    timeline.record("fat-done");
+                }
                 Ok(module)
             }
             LtoModuleCodegen::Thin(ref mut thin) => thin.optimize(cgcx, timeline),
@@ -223,66 +225,76 @@ fn fat_lto(cgcx: &CodegenContext,
         .filter(|&(_, module)| module.kind == ModuleKind::Regular)
         .map(|(i, module)| {
             let cost = unsafe {
-                llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod)
+                llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod())
             };
             (cost, i)
         })
         .max()
         .expect("must be codegen'ing at least one module");
     let module = modules.remove(costliest_module);
-    let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod;
-    info!("using {:?} as a base module", module.llmod_id);
-
-    // For all other modules we codegened we'll need to link them into our own
-    // bitcode. All modules were codegened in their own LLVM context, however,
-    // and we want to move everything to the same LLVM context. Currently the
-    // way we know of to do that is to serialize them to a string and them parse
-    // them later. Not great but hey, that's why it's "fat" LTO, right?
-    for module in modules {
-        let llvm = module.llvm().expect("can't lto pre-codegened modules");
-        let buffer = ModuleBuffer::new(llvm.llmod);
-        let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
-        serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
-    }
-
-    // For all serialized bitcode files we parse them and link them in as we did
-    // above, this is all mostly handled in C++. Like above, though, we don't
-    // know much about the memory management here so we err on the side of being
-    // save and persist everything with the original module.
     let mut serialized_bitcode = Vec::new();
-    let mut linker = Linker::new(llmod);
-    for (bc_decoded, name) in serialized_modules {
-        info!("linking {:?}", name);
-        time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || {
-            let data = bc_decoded.data();
-            linker.add(&data).map_err(|()| {
-                let msg = format!("failed to load bc of {:?}", name);
-                write::llvm_err(&diag_handler, msg)
-            })
-        })?;
-        timeline.record(&format!("link {:?}", name));
-        serialized_bitcode.push(bc_decoded);
-    }
-    drop(linker);
-    cgcx.save_temp_bitcode(&module, "lto.input");
+    {
+        let (llcx, llmod) = {
+            let llvm = module.llvm().expect("can't lto pre-codegened modules");
+            (&llvm.llcx, llvm.llmod())
+        };
+        info!("using {:?} as a base module", module.llmod_id);
+
+        // The linking steps below may produce errors and diagnostics within LLVM
+        // which we'd like to handle and print, so set up our diagnostic handlers
+        // (which get unregistered when they go out of scope below).
+        let _handler = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
+
+        // For all other modules we codegened we'll need to link them into our own
+        // bitcode. All modules were codegened in their own LLVM context, however,
+        // and we want to move everything to the same LLVM context. Currently the
+        // way we know of to do that is to serialize them to a string and them parse
+        // them later. Not great but hey, that's why it's "fat" LTO, right?
+        for module in modules {
+            let llvm = module.llvm().expect("can't lto pre-codegened modules");
+            let buffer = ModuleBuffer::new(llvm.llmod());
+            let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
+            serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
+        }
 
-    // Internalize everything that *isn't* in our whitelist to help strip out
-    // more modules and such
-    unsafe {
-        let ptr = symbol_white_list.as_ptr();
-        llvm::LLVMRustRunRestrictionPass(llmod,
-                                         ptr as *const *const libc::c_char,
-                                         symbol_white_list.len() as libc::size_t);
-        cgcx.save_temp_bitcode(&module, "lto.after-restriction");
-    }
+        // For all serialized bitcode files we parse them and link them in as we did
+        // above, this is all mostly handled in C++. Like above, though, we don't
+        // know much about the memory management here so we err on the side of being
+        // save and persist everything with the original module.
+        let mut linker = Linker::new(llmod);
+        for (bc_decoded, name) in serialized_modules {
+            info!("linking {:?}", name);
+            time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || {
+                let data = bc_decoded.data();
+                linker.add(&data).map_err(|()| {
+                    let msg = format!("failed to load bc of {:?}", name);
+                    write::llvm_err(&diag_handler, msg)
+                })
+            })?;
+            timeline.record(&format!("link {:?}", name));
+            serialized_bitcode.push(bc_decoded);
+        }
+        drop(linker);
+        cgcx.save_temp_bitcode(&module, "lto.input");
 
-    if cgcx.no_landing_pads {
+        // Internalize everything that *isn't* in our whitelist to help strip out
+        // more modules and such
         unsafe {
-            llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+            let ptr = symbol_white_list.as_ptr();
+            llvm::LLVMRustRunRestrictionPass(llmod,
+                                            ptr as *const *const libc::c_char,
+                                            symbol_white_list.len() as libc::size_t);
+            cgcx.save_temp_bitcode(&module, "lto.after-restriction");
+        }
+
+        if cgcx.no_landing_pads {
+            unsafe {
+                llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+            }
+            cgcx.save_temp_bitcode(&module, "lto.after-nounwind");
         }
-        cgcx.save_temp_bitcode(&module, "lto.after-nounwind");
+        timeline.record("passes");
     }
-    timeline.record("passes");
 
     Ok(vec![LtoModuleCodegen::Fat {
         module: Some(module),
@@ -290,10 +302,10 @@ fn fat_lto(cgcx: &CodegenContext,
     }])
 }
 
-struct Linker(llvm::LinkerRef);
+struct Linker<'a>(&'a mut llvm::Linker<'a>);
 
-impl Linker {
-    fn new(llmod: ModuleRef) -> Linker {
+impl Linker<'a> {
+    fn new(llmod: &'a llvm::Module) -> Self {
         unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) }
     }
 
@@ -310,9 +322,9 @@ fn add(&mut self, bytecode: &[u8]) -> Result<(), ()> {
     }
 }
 
-impl Drop for Linker {
+impl Drop for Linker<'a> {
     fn drop(&mut self) {
-        unsafe { llvm::LLVMRustLinkerFree(self.0); }
+        unsafe { llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _)); }
     }
 }
 
@@ -371,7 +383,7 @@ fn thin_lto(diag_handler: &Handler,
             info!("local module: {} - {}", i, module.llmod_id);
             let llvm = module.llvm().expect("can't lto precodegened module");
             let name = CString::new(module.llmod_id.clone()).unwrap();
-            let buffer = ThinBuffer::new(llvm.llmod);
+            let buffer = ThinBuffer::new(llvm.llmod());
             thin_modules.push(llvm::ThinLTOModule {
                 identifier: name.as_ptr(),
                 data: buffer.data().as_ptr(),
@@ -419,11 +431,10 @@ fn thin_lto(diag_handler: &Handler,
             thin_modules.len() as u32,
             symbol_white_list.as_ptr(),
             symbol_white_list.len() as u32,
-        );
-        if data.is_null() {
-            let msg = "failed to prepare thin LTO context".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
+        ).ok_or_else(|| {
+            write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string())
+        })?;
+
         let data = ThinData(data);
         info!("thin LTO data created");
         timeline.record("data");
@@ -448,8 +459,8 @@ fn thin_lto(diag_handler: &Handler,
 }
 
 fn run_pass_manager(cgcx: &CodegenContext,
-                    tm: TargetMachineRef,
-                    llmod: ModuleRef,
+                    tm: &llvm::TargetMachine,
+                    llmod: &llvm::Module,
                     config: &ModuleConfig,
                     thin: bool) {
     // Now we have one massive module inside of llmod. Time to run the
@@ -464,8 +475,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
 
         if config.verify_llvm_ir {
             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
-            assert!(!pass.is_null());
-            llvm::LLVMRustAddPass(pm, pass);
+            llvm::LLVMRustAddPass(pm, pass.unwrap());
         }
 
         // When optimizing for LTO we don't actually pass in `-O0`, but we force
@@ -499,8 +509,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
 
         if config.verify_llvm_ir {
             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
-            assert!(!pass.is_null());
-            llvm::LLVMRustAddPass(pm, pass);
+            llvm::LLVMRustAddPass(pm, pass.unwrap());
         }
 
         time_ext(cgcx.time_passes, None, "LTO passes", ||
@@ -525,13 +534,13 @@ fn data(&self) -> &[u8] {
     }
 }
 
-pub struct ModuleBuffer(*mut llvm::ModuleBuffer);
+pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer);
 
 unsafe impl Send for ModuleBuffer {}
 unsafe impl Sync for ModuleBuffer {}
 
 impl ModuleBuffer {
-    pub fn new(m: ModuleRef) -> ModuleBuffer {
+    pub fn new(m: &llvm::Module) -> ModuleBuffer {
         ModuleBuffer(unsafe {
             llvm::LLVMRustModuleBufferCreate(m)
         })
@@ -548,7 +557,7 @@ pub fn data(&self) -> &[u8] {
 
 impl Drop for ModuleBuffer {
     fn drop(&mut self) {
-        unsafe { llvm::LLVMRustModuleBufferFree(self.0); }
+        unsafe { llvm::LLVMRustModuleBufferFree(&mut *(self.0 as *mut _)); }
     }
 }
 
@@ -564,7 +573,7 @@ struct ThinShared {
     module_names: Vec<CString>,
 }
 
-struct ThinData(*mut llvm::ThinLTOData);
+struct ThinData(&'static mut llvm::ThinLTOData);
 
 unsafe impl Send for ThinData {}
 unsafe impl Sync for ThinData {}
@@ -572,18 +581,18 @@ unsafe impl Sync for ThinData {}
 impl Drop for ThinData {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMRustFreeThinLTOData(self.0);
+            llvm::LLVMRustFreeThinLTOData(&mut *(self.0 as *mut _));
         }
     }
 }
 
-pub struct ThinBuffer(*mut llvm::ThinLTOBuffer);
+pub struct ThinBuffer(&'static mut llvm::ThinLTOBuffer);
 
 unsafe impl Send for ThinBuffer {}
 unsafe impl Sync for ThinBuffer {}
 
 impl ThinBuffer {
-    pub fn new(m: ModuleRef) -> ThinBuffer {
+    pub fn new(m: &llvm::Module) -> ThinBuffer {
         unsafe {
             let buffer = llvm::LLVMRustThinLTOBufferCreate(m);
             ThinBuffer(buffer)
@@ -602,7 +611,7 @@ pub fn data(&self) -> &[u8] {
 impl Drop for ThinBuffer {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMRustThinLTOBufferFree(self.0);
+            llvm::LLVMRustThinLTOBufferFree(&mut *(self.0 as *mut _));
         }
     }
 }
@@ -640,19 +649,18 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
         // crates but for locally codegened modules we may be able to reuse
         // that LLVM Context and Module.
         let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
-        let llmod = llvm::LLVMRustParseBitcodeForThinLTO(
+        let llmod_raw = llvm::LLVMRustParseBitcodeForThinLTO(
             llcx,
             self.data().as_ptr(),
             self.data().len(),
             self.shared.module_names[self.idx].as_ptr(),
-        );
-        if llmod.is_null() {
+        ).ok_or_else(|| {
             let msg = "failed to parse bitcode for thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg));
-        }
+            write::llvm_err(&diag_handler, msg)
+        })? as *const _;
         let module = ModuleCodegen {
             source: ModuleSource::Codegened(ModuleLlvm {
-                llmod,
+                llmod_raw,
                 llcx,
                 tm,
             }),
@@ -660,104 +668,107 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
             name: self.name().to_string(),
             kind: ModuleKind::Regular,
         };
-        cgcx.save_temp_bitcode(&module, "thin-lto-input");
-
-        // Before we do much else find the "main" `DICompileUnit` that we'll be
-        // using below. If we find more than one though then rustc has changed
-        // in a way we're not ready for, so generate an ICE by returning
-        // an error.
-        let mut cu1 = ptr::null_mut();
-        let mut cu2 = ptr::null_mut();
-        llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
-        if !cu2.is_null() {
-            let msg = "multiple source DICompileUnits found".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
+        {
+            let llmod = module.llvm().unwrap().llmod();
+            cgcx.save_temp_bitcode(&module, "thin-lto-input");
+
+            // Before we do much else find the "main" `DICompileUnit` that we'll be
+            // using below. If we find more than one though then rustc has changed
+            // in a way we're not ready for, so generate an ICE by returning
+            // an error.
+            let mut cu1 = ptr::null_mut();
+            let mut cu2 = ptr::null_mut();
+            llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
+            if !cu2.is_null() {
+                let msg = "multiple source DICompileUnits found".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
 
-        // Like with "fat" LTO, get some better optimizations if landing pads
-        // are disabled by removing all landing pads.
-        if cgcx.no_landing_pads {
-            llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
-            cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind");
-            timeline.record("nounwind");
-        }
+            // Like with "fat" LTO, get some better optimizations if landing pads
+            // are disabled by removing all landing pads.
+            if cgcx.no_landing_pads {
+                llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+                cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind");
+                timeline.record("nounwind");
+            }
 
-        // Up next comes the per-module local analyses that we do for Thin LTO.
-        // Each of these functions is basically copied from the LLVM
-        // implementation and then tailored to suit this implementation. Ideally
-        // each of these would be supported by upstream LLVM but that's perhaps
-        // a patch for another day!
-        //
-        // You can find some more comments about these functions in the LLVM
-        // bindings we've got (currently `PassWrapper.cpp`)
-        if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
-        timeline.record("rename");
-        if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
-        timeline.record("resolve");
-        if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
-        }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
-        timeline.record("internalize");
-        if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
-            let msg = "failed to prepare thin LTO module".to_string();
-            return Err(write::llvm_err(&diag_handler, msg))
+            // Up next comes the per-module local analyses that we do for Thin LTO.
+            // Each of these functions is basically copied from the LLVM
+            // implementation and then tailored to suit this implementation. Ideally
+            // each of these would be supported by upstream LLVM but that's perhaps
+            // a patch for another day!
+            //
+            // You can find some more comments about these functions in the LLVM
+            // bindings we've got (currently `PassWrapper.cpp`)
+            if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
+            timeline.record("rename");
+            if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
+            timeline.record("resolve");
+            if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
+            timeline.record("internalize");
+            if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
+                let msg = "failed to prepare thin LTO module".to_string();
+                return Err(write::llvm_err(&diag_handler, msg))
+            }
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
+            timeline.record("import");
+
+            // Ok now this is a bit unfortunate. This is also something you won't
+            // find upstream in LLVM's ThinLTO passes! This is a hack for now to
+            // work around bugs in LLVM.
+            //
+            // First discovered in #45511 it was found that as part of ThinLTO
+            // importing passes LLVM will import `DICompileUnit` metadata
+            // information across modules. This means that we'll be working with one
+            // LLVM module that has multiple `DICompileUnit` instances in it (a
+            // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
+            // bugs in LLVM's backend which generates invalid DWARF in a situation
+            // like this:
+            //
+            //  https://bugs.llvm.org/show_bug.cgi?id=35212
+            //  https://bugs.llvm.org/show_bug.cgi?id=35562
+            //
+            // While the first bug there is fixed the second ended up causing #46346
+            // which was basically a resurgence of #45511 after LLVM's bug 35212 was
+            // fixed.
+            //
+            // This function below is a huge hack around this problem. The function
+            // below is defined in `PassWrapper.cpp` and will basically "merge"
+            // all `DICompileUnit` instances in a module. Basically it'll take all
+            // the objects, rewrite all pointers of `DISubprogram` to point to the
+            // first `DICompileUnit`, and then delete all the other units.
+            //
+            // This is probably mangling to the debug info slightly (but hopefully
+            // not too much) but for now at least gets LLVM to emit valid DWARF (or
+            // so it appears). Hopefully we can remove this once upstream bugs are
+            // fixed in LLVM.
+            llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-patch");
+            timeline.record("patch");
+
+            // Alright now that we've done everything related to the ThinLTO
+            // analysis it's time to run some optimizations! Here we use the same
+            // `run_pass_manager` as the "fat" LTO above except that we tell it to
+            // populate a thin-specific pass manager, which presumably LLVM treats a
+            // little differently.
+            info!("running thin lto passes over {}", module.name);
+            let config = cgcx.config(module.kind);
+            run_pass_manager(cgcx, module.llvm().unwrap().tm, llmod, config, true);
+            cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
+            timeline.record("thin-done");
         }
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
-        timeline.record("import");
-
-        // Ok now this is a bit unfortunate. This is also something you won't
-        // find upstream in LLVM's ThinLTO passes! This is a hack for now to
-        // work around bugs in LLVM.
-        //
-        // First discovered in #45511 it was found that as part of ThinLTO
-        // importing passes LLVM will import `DICompileUnit` metadata
-        // information across modules. This means that we'll be working with one
-        // LLVM module that has multiple `DICompileUnit` instances in it (a
-        // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
-        // bugs in LLVM's backend which generates invalid DWARF in a situation
-        // like this:
-        //
-        //  https://bugs.llvm.org/show_bug.cgi?id=35212
-        //  https://bugs.llvm.org/show_bug.cgi?id=35562
-        //
-        // While the first bug there is fixed the second ended up causing #46346
-        // which was basically a resurgence of #45511 after LLVM's bug 35212 was
-        // fixed.
-        //
-        // This function below is a huge hack around this problem. The function
-        // below is defined in `PassWrapper.cpp` and will basically "merge"
-        // all `DICompileUnit` instances in a module. Basically it'll take all
-        // the objects, rewrite all pointers of `DISubprogram` to point to the
-        // first `DICompileUnit`, and then delete all the other units.
-        //
-        // This is probably mangling to the debug info slightly (but hopefully
-        // not too much) but for now at least gets LLVM to emit valid DWARF (or
-        // so it appears). Hopefully we can remove this once upstream bugs are
-        // fixed in LLVM.
-        llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-patch");
-        timeline.record("patch");
-
-        // Alright now that we've done everything related to the ThinLTO
-        // analysis it's time to run some optimizations! Here we use the same
-        // `run_pass_manager` as the "fat" LTO above except that we tell it to
-        // populate a thin-specific pass manager, which presumably LLVM treats a
-        // little differently.
-        info!("running thin lto passes over {}", module.name);
-        let config = cgcx.config(module.kind);
-        run_pass_manager(cgcx, tm, llmod, config, true);
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
-        timeline.record("thin-done");
 
         Ok(module)
     }
index 48de2f3beedfb68dc846eff0f9ad8c38107228e0..02434b7be0bda22aa1d024d96f6e0d14c694dc83 100644 (file)
@@ -37,12 +37,12 @@ pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel {
 
 fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel {
     match crate_type {
-        config::CrateTypeExecutable |
-        config::CrateTypeStaticlib  |
-        config::CrateTypeProcMacro  |
-        config::CrateTypeCdylib     => SymbolExportLevel::C,
-        config::CrateTypeRlib       |
-        config::CrateTypeDylib      => SymbolExportLevel::Rust,
+        config::CrateType::Executable |
+        config::CrateType::Staticlib  |
+        config::CrateType::ProcMacro  |
+        config::CrateType::Cdylib     => SymbolExportLevel::C,
+        config::CrateType::Rlib       |
+        config::CrateType::Dylib      => SymbolExportLevel::Rust,
     }
 }
 
@@ -235,14 +235,14 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
+    if tcx.sess.crate_types.borrow().contains(&config::CrateType::Dylib) {
         let symbol_name = metadata_symbol_name(tcx);
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
 
         symbols.push((exported_symbol, SymbolExportLevel::Rust));
     }
 
-    if tcx.share_generics() && tcx.local_crate_exports_generics() {
+    if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() {
         use rustc::mir::mono::{Linkage, Visibility, MonoItem};
         use rustc::ty::InstanceDef;
 
index d36142af56c6540ad15af51d052e1bace989f8c9..a5c6a0d5cd690e4828b2b4595db3220b9a7cb291 100644 (file)
 use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir};
 use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
 use rustc::middle::cstore::{LinkMeta, EncodedMetadata};
-use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePasses,
-                             AllPasses, Sanitizer, Lto};
+use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
 use rustc::session::Session;
 use rustc::util::nodemap::FxHashMap;
 use time_graph::{self, TimeGraph, Timeline};
-use llvm;
-use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
-use llvm::{SMDiagnosticRef, ContextRef};
+use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
 use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind};
 use CrateInfo;
 use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -94,9 +91,9 @@ pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
 
 pub fn write_output_file(
         handler: &errors::Handler,
-        target: llvm::TargetMachineRef,
-        pm: llvm::PassManagerRef,
-        m: ModuleRef,
+        target: &'ll llvm::TargetMachine,
+        pm: &llvm::PassManager<'ll>,
+        m: &'ll llvm::Module,
         output: &Path,
         file_type: llvm::FileType) -> Result<(), FatalError> {
     unsafe {
@@ -130,7 +127,10 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
     }
 }
 
-pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachineRef {
+pub fn create_target_machine(
+    sess: &Session,
+    find_features: bool,
+) -> &'static mut llvm::TargetMachine {
     target_machine_factory(sess, find_features)().unwrap_or_else(|err| {
         llvm_err(sess.diagnostic(), err).raise()
     })
@@ -140,7 +140,7 @@ pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachi
 // that `is_pie_binary` is false. When we discover LLVM target features
 // `sess.crate_types` is uninitialized so we cannot access it.
 pub fn target_machine_factory(sess: &Session, find_features: bool)
-    -> Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync>
+    -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync>
 {
     let reloc_model = get_reloc_model(sess);
 
@@ -199,12 +199,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
             )
         };
 
-        if tm.is_null() {
-            Err(format!("Could not create LLVM TargetMachine for triple: {}",
-                        triple.to_str().unwrap()))
-        } else {
-            Ok(tm)
-        }
+        tm.ok_or_else(|| {
+            format!("Could not create LLVM TargetMachine for triple: {}",
+                    triple.to_str().unwrap())
+        })
     })
 }
 
@@ -343,10 +341,10 @@ pub struct CodegenContext {
     regular_module_config: Arc<ModuleConfig>,
     metadata_module_config: Arc<ModuleConfig>,
     allocator_module_config: Arc<ModuleConfig>,
-    pub tm_factory: Arc<dyn Fn() -> Result<TargetMachineRef, String> + Send + Sync>,
+    pub tm_factory: Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync>,
     pub msvc_imps_needed: bool,
     pub target_pointer_width: String,
-    debuginfo: config::DebugInfoLevel,
+    debuginfo: config::DebugInfo,
 
     // Number of cgus excluding the allocator/metadata modules
     pub total_cgus: usize,
@@ -392,21 +390,21 @@ pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) {
             let cgu = Some(&module.name[..]);
             let path = self.output_filenames.temp_path_ext(&ext, cgu);
             let cstr = path2cstr(&path);
-            let llmod = module.llvm().unwrap().llmod;
+            let llmod = module.llvm().unwrap().llmod();
             llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
         }
     }
 }
 
-struct DiagnosticHandlers<'a> {
+pub struct DiagnosticHandlers<'a> {
     data: *mut (&'a CodegenContext, &'a Handler),
-    llcx: ContextRef,
+    llcx: &'a llvm::Context,
 }
 
 impl<'a> DiagnosticHandlers<'a> {
-    fn new(cgcx: &'a CodegenContext,
-           handler: &'a Handler,
-           llcx: ContextRef) -> DiagnosticHandlers<'a> {
+    pub fn new(cgcx: &'a CodegenContext,
+               handler: &'a Handler,
+               llcx: &'a llvm::Context) -> Self {
         let data = Box::into_raw(Box::new((cgcx, handler)));
         unsafe {
             llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _);
@@ -433,7 +431,7 @@ fn drop(&mut self) {
     cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string());
 }
 
-unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
+unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic,
                                         user: *const c_void,
                                         cookie: c_uint) {
     if user.is_null() {
@@ -447,7 +445,7 @@ fn drop(&mut self) {
     report_inline_asm(cgcx, &msg, cookie);
 }
 
-unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
+unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
     if user.is_null() {
         return
     }
@@ -462,8 +460,8 @@ fn drop(&mut self) {
 
         llvm::diagnostic::Optimization(opt) => {
             let enabled = match cgcx.remark {
-                AllPasses => true,
-                SomePasses(ref v) => v.iter().any(|s| *s == opt.pass_name),
+                Passes::All => true,
+                Passes::Some(ref v) => v.iter().any(|s| *s == opt.pass_name),
             };
 
             if enabled {
@@ -476,10 +474,11 @@ fn drop(&mut self) {
                                                 opt.message));
             }
         }
-        llvm::diagnostic::PGO(diagnostic_ref) => {
+        llvm::diagnostic::PGO(diagnostic_ref) |
+        llvm::diagnostic::Linker(diagnostic_ref) => {
             let msg = llvm::build_string(|s| {
                 llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
-            }).expect("non-UTF8 PGO diagnostic");
+            }).expect("non-UTF8 diagnostic");
             diag_handler.warn(&msg);
         }
         llvm::diagnostic::UnknownDiagnostic(..) => {},
@@ -495,7 +494,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
     -> Result<(), FatalError>
 {
     let (llmod, llcx, tm) = match module.source {
-        ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
+        ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
         ModuleSource::Preexisting(_) => {
             bug!("optimize_and_codegen: called with ModuleSource::Preexisting")
         }
@@ -520,50 +519,52 @@ unsafe fn optimize(cgcx: &CodegenContext,
         let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
         let mpm = llvm::LLVMCreatePassManager();
 
-        // If we're verifying or linting, add them to the function pass
-        // manager.
-        let addpass = |pass_name: &str| {
-            let pass_name = CString::new(pass_name).unwrap();
-            let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr());
-            if pass.is_null() {
-                return false;
-            }
-            let pass_manager = match llvm::LLVMRustPassKind(pass) {
-                llvm::PassKind::Function => fpm,
-                llvm::PassKind::Module => mpm,
-                llvm::PassKind::Other => {
-                    diag_handler.err("Encountered LLVM pass kind we can't handle");
-                    return true
-                },
+        {
+            // If we're verifying or linting, add them to the function pass
+            // manager.
+            let addpass = |pass_name: &str| {
+                let pass_name = CString::new(pass_name).unwrap();
+                let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) {
+                    Some(pass) => pass,
+                    None => return false,
+                };
+                let pass_manager = match llvm::LLVMRustPassKind(pass) {
+                    llvm::PassKind::Function => &*fpm,
+                    llvm::PassKind::Module => &*mpm,
+                    llvm::PassKind::Other => {
+                        diag_handler.err("Encountered LLVM pass kind we can't handle");
+                        return true
+                    },
+                };
+                llvm::LLVMRustAddPass(pass_manager, pass);
+                true
             };
-            llvm::LLVMRustAddPass(pass_manager, pass);
-            true
-        };
 
-        if config.verify_llvm_ir { assert!(addpass("verify")); }
-        if !config.no_prepopulate_passes {
-            llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
-            llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
-            let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
-            let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal;
-            with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
-                llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
-                llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
-            })
-        }
+            if config.verify_llvm_ir { assert!(addpass("verify")); }
+            if !config.no_prepopulate_passes {
+                llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
+                llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
+                let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
+                let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal;
+                with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
+                    llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
+                    llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
+                })
+            }
 
-        for pass in &config.passes {
-            if !addpass(pass) {
-                diag_handler.warn(&format!("unknown pass `{}`, ignoring",
-                                           pass));
+            for pass in &config.passes {
+                if !addpass(pass) {
+                    diag_handler.warn(&format!("unknown pass `{}`, ignoring",
+                                            pass));
+                }
             }
-        }
 
-        for pass in &cgcx.plugin_passes {
-            if !addpass(pass) {
-                diag_handler.err(&format!("a plugin asked for LLVM pass \
-                                           `{}` but LLVM does not \
-                                           recognize it", pass));
+            for pass in &cgcx.plugin_passes {
+                if !addpass(pass) {
+                    diag_handler.err(&format!("a plugin asked for LLVM pass \
+                                            `{}` but LLVM does not \
+                                            recognize it", pass));
+                }
             }
         }
 
@@ -617,192 +618,191 @@ unsafe fn codegen(cgcx: &CodegenContext,
     -> Result<CompiledModule, FatalError>
 {
     timeline.record("codegen");
-    let (llmod, llcx, tm) = match module.source {
-        ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
-        ModuleSource::Preexisting(_) => {
-            bug!("codegen: called with ModuleSource::Preexisting")
-        }
-    };
-    let module_name = module.name.clone();
-    let module_name = Some(&module_name[..]);
-    let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
-
-    if cgcx.msvc_imps_needed {
-        create_msvc_imps(cgcx, llcx, llmod);
-    }
-
-    // A codegen-specific pass manager is used to generate object
-    // files for an LLVM module.
-    //
-    // Apparently each of these pass managers is a one-shot kind of
-    // thing, so we create a new one for each type of output. The
-    // pass manager passed to the closure should be ensured to not
-    // escape the closure itself, and the manager should only be
-    // used once.
-    unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
-                                 llmod: ModuleRef,
-                                 no_builtins: bool,
-                                 f: F) -> R
-        where F: FnOnce(PassManagerRef) -> R,
     {
-        let cpm = llvm::LLVMCreatePassManager();
-        llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
-        llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
-        f(cpm)
-    }
-
-    // If we don't have the integrated assembler, then we need to emit asm
-    // from LLVM and use `gcc` to create the object file.
-    let asm_to_obj = config.emit_obj && config.no_integrated_as;
-
-    // Change what we write and cleanup based on whether obj files are
-    // just llvm bitcode. In that case write bitcode, and possibly
-    // delete the bitcode if it wasn't requested. Don't generate the
-    // machine code, instead copy the .o file from the .bc
-    let write_bc = config.emit_bc || config.obj_is_bitcode;
-    let rm_bc = !config.emit_bc && config.obj_is_bitcode;
-    let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
-    let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
-
-    let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
-    let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
-
-
-    if write_bc || config.emit_bc_compressed || config.embed_bitcode {
-        let thin;
-        let old;
-        let data = if llvm::LLVMRustThinLTOAvailable() {
-            thin = ThinBuffer::new(llmod);
-            thin.data()
-        } else {
-            old = ModuleBuffer::new(llmod);
-            old.data()
+        let (llmod, llcx, tm) = match module.source {
+            ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm),
+            ModuleSource::Preexisting(_) => {
+                bug!("codegen: called with ModuleSource::Preexisting")
+            }
         };
-        timeline.record("make-bc");
+        let module_name = module.name.clone();
+        let module_name = Some(&module_name[..]);
+        let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
 
-        if write_bc {
-            if let Err(e) = fs::write(&bc_out, data) {
-                diag_handler.err(&format!("failed to write bytecode: {}", e));
-            }
-            timeline.record("write-bc");
+        if cgcx.msvc_imps_needed {
+            create_msvc_imps(cgcx, llcx, llmod);
         }
 
-        if config.embed_bitcode {
-            embed_bitcode(cgcx, llcx, llmod, Some(data));
-            timeline.record("embed-bc");
-        }
+        // A codegen-specific pass manager is used to generate object
+        // files for an LLVM module.
+        //
+        // Apparently each of these pass managers is a one-shot kind of
+        // thing, so we create a new one for each type of output. The
+        // pass manager passed to the closure should be ensured to not
+        // escape the closure itself, and the manager should only be
+        // used once.
+        unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine,
+                                    llmod: &'ll llvm::Module,
+                                    no_builtins: bool,
+                                    f: F) -> R
+            where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
+        {
+            let cpm = llvm::LLVMCreatePassManager();
+            llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
+            llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
+            f(cpm)
+        }
+
+        // If we don't have the integrated assembler, then we need to emit asm
+        // from LLVM and use `gcc` to create the object file.
+        let asm_to_obj = config.emit_obj && config.no_integrated_as;
+
+        // Change what we write and cleanup based on whether obj files are
+        // just llvm bitcode. In that case write bitcode, and possibly
+        // delete the bitcode if it wasn't requested. Don't generate the
+        // machine code, instead copy the .o file from the .bc
+        let write_bc = config.emit_bc || config.obj_is_bitcode;
+        let rm_bc = !config.emit_bc && config.obj_is_bitcode;
+        let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
+        let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
+
+        let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
+        let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
+
+
+        if write_bc || config.emit_bc_compressed || config.embed_bitcode {
+            let thin;
+            let old;
+            let data = if llvm::LLVMRustThinLTOAvailable() {
+                thin = ThinBuffer::new(llmod);
+                thin.data()
+            } else {
+                old = ModuleBuffer::new(llmod);
+                old.data()
+            };
+            timeline.record("make-bc");
 
-        if config.emit_bc_compressed {
-            let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
-            let data = bytecode::encode(&module.llmod_id, data);
-            if let Err(e) = fs::write(&dst, data) {
-                diag_handler.err(&format!("failed to write bytecode: {}", e));
+            if write_bc {
+                if let Err(e) = fs::write(&bc_out, data) {
+                    diag_handler.err(&format!("failed to write bytecode: {}", e));
+                }
+                timeline.record("write-bc");
             }
-            timeline.record("compress-bc");
-        }
-    } else if config.embed_bitcode_marker {
-        embed_bitcode(cgcx, llcx, llmod, None);
-    }
 
-    time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
-         || -> Result<(), FatalError> {
-        if config.emit_ir {
-            let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
-            let out = path2cstr(&out);
-
-            extern "C" fn demangle_callback(input_ptr: *const c_char,
-                                            input_len: size_t,
-                                            output_ptr: *mut c_char,
-                                            output_len: size_t) -> size_t {
-                let input = unsafe {
-                    slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
-                };
+            if config.embed_bitcode {
+                embed_bitcode(cgcx, llcx, llmod, Some(data));
+                timeline.record("embed-bc");
+            }
 
-                let input = match str::from_utf8(input) {
-                    Ok(s) => s,
-                    Err(_) => return 0,
-                };
+            if config.emit_bc_compressed {
+                let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
+                let data = bytecode::encode(&module.llmod_id, data);
+                if let Err(e) = fs::write(&dst, data) {
+                    diag_handler.err(&format!("failed to write bytecode: {}", e));
+                }
+                timeline.record("compress-bc");
+            }
+        } else if config.embed_bitcode_marker {
+            embed_bitcode(cgcx, llcx, llmod, None);
+        }
+
+        time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
+            || -> Result<(), FatalError> {
+            if config.emit_ir {
+                let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
+                let out = path2cstr(&out);
+
+                extern "C" fn demangle_callback(input_ptr: *const c_char,
+                                                input_len: size_t,
+                                                output_ptr: *mut c_char,
+                                                output_len: size_t) -> size_t {
+                    let input = unsafe {
+                        slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
+                    };
 
-                let output = unsafe {
-                    slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
-                };
-                let mut cursor = io::Cursor::new(output);
+                    let input = match str::from_utf8(input) {
+                        Ok(s) => s,
+                        Err(_) => return 0,
+                    };
 
-                let demangled = match rustc_demangle::try_demangle(input) {
-                    Ok(d) => d,
-                    Err(_) => return 0,
-                };
+                    let output = unsafe {
+                        slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
+                    };
+                    let mut cursor = io::Cursor::new(output);
+
+                    let demangled = match rustc_demangle::try_demangle(input) {
+                        Ok(d) => d,
+                        Err(_) => return 0,
+                    };
+
+                    if let Err(_) = write!(cursor, "{:#}", demangled) {
+                        // Possible only if provided buffer is not big enough
+                        return 0;
+                    }
 
-                if let Err(_) = write!(cursor, "{:#}", demangled) {
-                    // Possible only if provided buffer is not big enough
-                    return 0;
+                    cursor.position() as size_t
                 }
 
-                cursor.position() as size_t
+                with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                    llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
+                    llvm::LLVMDisposePassManager(cpm);
+                });
+                timeline.record("ir");
             }
 
-            with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
-                llvm::LLVMDisposePassManager(cpm);
-            });
-            timeline.record("ir");
-        }
-
-        if config.emit_asm || asm_to_obj {
-            let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+            if config.emit_asm || asm_to_obj {
+                let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
 
-            // We can't use the same module for asm and binary output, because that triggers
-            // various errors like invalid IR or broken binaries, so we might have to clone the
-            // module to produce the asm output
-            let llmod = if config.emit_obj {
-                llvm::LLVMCloneModule(llmod)
-            } else {
-                llmod
-            };
-            with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                write_output_file(diag_handler, tm, cpm, llmod, &path,
-                                  llvm::FileType::AssemblyFile)
-            })?;
-            if config.emit_obj {
-                llvm::LLVMDisposeModule(llmod);
+                // We can't use the same module for asm and binary output, because that triggers
+                // various errors like invalid IR or broken binaries, so we might have to clone the
+                // module to produce the asm output
+                let llmod = if config.emit_obj {
+                    llvm::LLVMCloneModule(llmod)
+                } else {
+                    llmod
+                };
+                with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                    write_output_file(diag_handler, tm, cpm, llmod, &path,
+                                    llvm::FileType::AssemblyFile)
+                })?;
+                timeline.record("asm");
             }
-            timeline.record("asm");
-        }
 
-        if write_obj {
-            with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
-                                  llvm::FileType::ObjectFile)
-            })?;
-            timeline.record("obj");
-        } else if asm_to_obj {
-            let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
-            run_assembler(cgcx, diag_handler, &assembly, &obj_out);
-            timeline.record("asm_to_obj");
-
-            if !config.emit_asm && !cgcx.save_temps {
-                drop(fs::remove_file(&assembly));
+            if write_obj {
+                with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                    write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
+                                    llvm::FileType::ObjectFile)
+                })?;
+                timeline.record("obj");
+            } else if asm_to_obj {
+                let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+                run_assembler(cgcx, diag_handler, &assembly, &obj_out);
+                timeline.record("asm_to_obj");
+
+                if !config.emit_asm && !cgcx.save_temps {
+                    drop(fs::remove_file(&assembly));
+                }
             }
-        }
 
-        Ok(())
-    })?;
+            Ok(())
+        })?;
 
-    if copy_bc_to_obj {
-        debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
-        if let Err(e) = link_or_copy(&bc_out, &obj_out) {
-            diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+        if copy_bc_to_obj {
+            debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
+            if let Err(e) = link_or_copy(&bc_out, &obj_out) {
+                diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+            }
         }
-    }
 
-    if rm_bc {
-        debug!("removing_bitcode {:?}", bc_out);
-        if let Err(e) = fs::remove_file(&bc_out) {
-            diag_handler.err(&format!("failed to remove bitcode: {}", e));
+        if rm_bc {
+            debug!("removing_bitcode {:?}", bc_out);
+            if let Err(e) = fs::remove_file(&bc_out) {
+                diag_handler.err(&format!("failed to remove bitcode: {}", e));
+            }
         }
-    }
 
-    drop(handlers);
+        drop(handlers);
+    }
     Ok(module.into_compiled_module(config.emit_obj,
                                    config.emit_bc,
                                    config.emit_bc_compressed,
@@ -828,13 +828,13 @@ extern "C" fn demangle_callback(input_ptr: *const c_char,
 /// Basically all of this is us attempting to follow in the footsteps of clang
 /// on iOS. See #35968 for lots more info.
 unsafe fn embed_bitcode(cgcx: &CodegenContext,
-                        llcx: ContextRef,
-                        llmod: ModuleRef,
+                        llcx: &llvm::Context,
+                        llmod: &llvm::Module,
                         bitcode: Option<&[u8]>) {
     let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
     let llglobal = llvm::LLVMAddGlobal(
         llmod,
-        val_ty(llconst).to_ref(),
+        val_ty(llconst),
         "rustc.embedded.module\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
@@ -854,7 +854,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
     let llconst = C_bytes_in_context(llcx, &[]);
     let llglobal = llvm::LLVMAddGlobal(
         llmod,
-        val_ty(llconst).to_ref(),
+        val_ty(llconst),
         "rustc.embedded.cmdline\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
@@ -874,7 +874,7 @@ pub(crate) struct CompiledModules {
 }
 
 fn need_crate_bitcode_for_rlib(sess: &Session) -> bool {
-    sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
+    sess.crate_types.borrow().contains(&config::CrateType::Rlib) &&
     sess.opts.output_types.contains_key(&OutputType::Exe)
 }
 
@@ -1340,7 +1340,7 @@ fn execute_work_item(cgcx: &CodegenContext,
                 // anything about it yet until we've got a final product.
                 Lto::Yes | Lto::Fat | Lto::Thin => {
                     cgcx.crate_types.len() != 1 ||
-                        cgcx.crate_types[0] != config::CrateTypeRlib
+                        cgcx.crate_types[0] != config::CrateType::Rlib
                 }
 
                 // When we're automatically doing ThinLTO for multi-codegen-unit
@@ -2050,11 +2050,11 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path,
     }
 }
 
-pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
+pub unsafe fn with_llvm_pmb(llmod: &llvm::Module,
                             config: &ModuleConfig,
                             opt_level: llvm::CodeGenOptLevel,
                             prepare_for_thin_lto: bool,
-                            f: &mut dyn FnMut(llvm::PassManagerBuilderRef)) {
+                            f: &mut dyn FnMut(&llvm::PassManagerBuilder)) {
     use std::ptr;
 
     // Create the PassManagerBuilder for LLVM. We configure it with
@@ -2345,7 +2345,7 @@ pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt,
 
 fn msvc_imps_needed(tcx: TyCtxt) -> bool {
     tcx.sess.target.target.options.is_like_msvc &&
-        tcx.sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib)
+        tcx.sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateType::Rlib)
 }
 
 // Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
@@ -2353,7 +2353,7 @@ fn msvc_imps_needed(tcx: TyCtxt) -> bool {
 // when using MSVC linker.  We do this only for data, as linker can fix up
 // code references on its own.
 // See #26591, #27438
-fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) {
+fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) {
     if !cgcx.msvc_imps_needed {
         return
     }
@@ -2383,7 +2383,7 @@ fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) {
             .collect::<Vec<_>>();
         for (imp_name, val) in globals {
             let imp = llvm::LLVMAddGlobal(llmod,
-                                          i8p_ty.to_ref(),
+                                          i8p_ty,
                                           imp_name.as_ptr() as *const _);
             llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty));
             llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
index 223c04f420f3ff978576cf7f7ad044a4faf9cd37..41336165684f61ff630eb59570c7653610dbd0b9 100644 (file)
 //!
 //! Hopefully useful general knowledge about codegen:
 //!
-//!   * There's no way to find out the Ty type of a ValueRef.  Doing so
+//!   * There's no way to find out the Ty type of a Value.  Doing so
 //!     would be "trying to get the eggs out of an omelette" (credit:
-//!     pcwalton).  You can, instead, find out its TypeRef by calling val_ty,
-//!     but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int,
-//!     int) and rec(x=int, y=int, z=int) will have the same TypeRef.
+//!     pcwalton).  You can, instead, find out its llvm::Type by calling val_ty,
+//!     but one llvm::Type corresponds to many `Ty`s; for instance, tup(int, int,
+//!     int) and rec(x=int, y=int, z=int) will have the same llvm::Type.
 
 use super::ModuleLlvm;
 use super::ModuleSource;
@@ -30,9 +30,8 @@
 
 use abi;
 use back::link;
-use back::write::{self, OngoingCodegen, create_target_machine};
-use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
-use llvm;
+use back::write::{self, OngoingCodegen};
+use llvm::{self, TypeKind, get_param};
 use metadata;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::middle::lang_items::StartFnLangItem;
@@ -46,7 +45,8 @@
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
 use rustc::middle::exported_symbols;
 use rustc::util::common::{time, print_time_passes_entry};
-use rustc::session::config::{self, NoDebugInfo};
+use rustc::util::profiling::ProfileCategory;
+use rustc::session::config::{self, DebugInfo, EntryFnType};
 use rustc::session::Session;
 use rustc_incremental;
 use allocator;
@@ -59,7 +59,7 @@
 use rustc_mir::monomorphize::item::DefPathBasedNames;
 use common::{self, C_struct_in_context, C_array, val_ty};
 use consts;
-use context::{self, CodegenCx};
+use context::CodegenCx;
 use debuginfo;
 use declare;
 use meth;
@@ -77,7 +77,6 @@
 
 use std::any::Any;
 use std::ffi::CString;
-use std::str;
 use std::sync::Arc;
 use std::time::{Instant, Duration};
 use std::i32;
 use syntax::attr;
 use rustc::hir::{self, CodegenFnAttrs};
 
+use value::Value;
+
 use mir::operand::OperandValue;
 
 use rustc_codegen_utils::check_for_rustc_errors_attr;
 
-pub struct StatRecorder<'a, 'tcx: 'a> {
-    cx: &'a CodegenCx<'a, 'tcx>,
+pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll> {
+    cx: &'a CodegenCx<'ll, 'tcx>,
     name: Option<String>,
     istart: usize,
 }
 
-impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
-    pub fn new(cx: &'a CodegenCx<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> {
+impl StatRecorder<'a, 'll, 'tcx> {
+    pub fn new(cx: &'a CodegenCx<'ll, 'tcx>, name: String) -> Self {
         let istart = cx.stats.borrow().n_llvm_insns;
         StatRecorder {
             cx,
@@ -109,7 +110,7 @@ pub fn new(cx: &'a CodegenCx<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx>
     }
 }
 
-impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
+impl Drop for StatRecorder<'a, 'll, 'tcx> {
     fn drop(&mut self) {
         if self.cx.sess().codegen_stats() {
             let mut stats = self.cx.stats.borrow_mut();
@@ -156,14 +157,14 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate {
     }
 }
 
-pub fn compare_simd_types<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    lhs: ValueRef,
-    rhs: ValueRef,
+pub fn compare_simd_types(
+    bx: &Builder<'a, 'll, 'tcx>,
+    lhs: &'ll Value,
+    rhs: &'ll Value,
     t: Ty<'tcx>,
-    ret_ty: Type,
+    ret_ty: &'ll Type,
     op: hir::BinOpKind
-) -> ValueRef {
+) -> &'ll Value {
     let signed = match t.sty {
         ty::TyFloat(_) => {
             let cmp = bin_op_to_fcmp_predicate(op);
@@ -188,11 +189,12 @@ pub fn compare_simd_types<'a, 'tcx>(
 /// The `old_info` argument is a bit funny. It is intended for use
 /// in an upcast, where the new vtable for an object will be derived
 /// from the old one.
-pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
-                                source: Ty<'tcx>,
-                                target: Ty<'tcx>,
-                                old_info: Option<ValueRef>)
-                                -> ValueRef {
+pub fn unsized_info(
+    cx: &CodegenCx<'ll, 'tcx>,
+    source: Ty<'tcx>,
+    target: Ty<'tcx>,
+    old_info: Option<&'ll Value>,
+) -> &'ll Value {
     let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::TyArray(_, len), &ty::TySlice(_)) => {
@@ -217,12 +219,12 @@ pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
 }
 
 /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
-pub fn unsize_thin_ptr<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    src: ValueRef,
+pub fn unsize_thin_ptr(
+    bx: &Builder<'a, 'll, 'tcx>,
+    src: &'ll Value,
     src_ty: Ty<'tcx>,
     dst_ty: Ty<'tcx>
-) -> (ValueRef, ValueRef) {
+) -> (&'ll Value, &'ll Value) {
     debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty);
     match (&src_ty.sty, &dst_ty.sty) {
         (&ty::TyRef(_, a, _),
@@ -272,9 +274,11 @@ pub fn unsize_thin_ptr<'a, 'tcx>(
 
 /// Coerce `src`, which is a reference to a value of type `src_ty`,
 /// to a value of type `dst_ty` and store the result in `dst`
-pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                                     src: PlaceRef<'tcx>,
-                                     dst: PlaceRef<'tcx>) {
+pub fn coerce_unsized_into(
+    bx: &Builder<'a, 'll, 'tcx>,
+    src: PlaceRef<'ll, 'tcx>,
+    dst: PlaceRef<'ll, 'tcx>
+) {
     let src_ty = src.layout.ty;
     let dst_ty = dst.layout.ty;
     let coerce_ptr = || {
@@ -330,28 +334,28 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 }
 
 pub fn cast_shift_expr_rhs(
-    cx: &Builder, op: hir::BinOpKind, lhs: ValueRef, rhs: ValueRef
-) -> ValueRef {
+    cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
+) -> &'ll Value {
     cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b))
 }
 
-fn cast_shift_rhs<F, G>(op: hir::BinOpKind,
-                        lhs: ValueRef,
-                        rhs: ValueRef,
+fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
+                        lhs: &'ll Value,
+                        rhs: &'ll Value,
                         trunc: F,
                         zext: G)
-                        -> ValueRef
-    where F: FnOnce(ValueRef, Type) -> ValueRef,
-          G: FnOnce(ValueRef, Type) -> ValueRef
+                        -> &'ll Value
+    where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value,
+          G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value
 {
     // Shifts may have any size int on the rhs
     if op.is_shift() {
         let mut rhs_llty = val_ty(rhs);
         let mut lhs_llty = val_ty(lhs);
-        if rhs_llty.kind() == Vector {
+        if rhs_llty.kind() == TypeKind::Vector {
             rhs_llty = rhs_llty.element_type()
         }
-        if lhs_llty.kind() == Vector {
+        if lhs_llty.kind() == TypeKind::Vector {
             lhs_llty = lhs_llty.element_type()
         }
         let rhs_sz = rhs_llty.int_width();
@@ -379,12 +383,12 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
     sess.target.target.options.is_like_msvc
 }
 
-pub fn call_assume<'a, 'tcx>(bx: &Builder<'a, 'tcx>, val: ValueRef) {
+pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) {
     let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
     bx.call(assume_intrinsic, &[val], None);
 }
 
-pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
+pub fn from_immediate(bx: &Builder<'_, 'll, '_>, val: &'ll Value) -> &'ll Value {
     if val_ty(val) == Type::i1(bx.cx) {
         bx.zext(val, Type::i8(bx.cx))
     } else {
@@ -392,26 +396,36 @@ pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
     }
 }
 
-pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
+pub fn to_immediate(
+    bx: &Builder<'_, 'll, '_>,
+    val: &'ll Value,
+    layout: layout::TyLayout,
+) -> &'ll Value {
     if let layout::Abi::Scalar(ref scalar) = layout.abi {
         return to_immediate_scalar(bx, val, scalar);
     }
     val
 }
 
-pub fn to_immediate_scalar(bx: &Builder, val: ValueRef, scalar: &layout::Scalar) -> ValueRef {
+pub fn to_immediate_scalar(
+    bx: &Builder<'_, 'll, '_>,
+    val: &'ll Value,
+    scalar: &layout::Scalar,
+) -> &'ll Value {
     if scalar.is_bool() {
         return bx.trunc(val, Type::i1(bx.cx));
     }
     val
 }
 
-pub fn call_memcpy(bx: &Builder,
-                   dst: ValueRef,
-                   src: ValueRef,
-                   n_bytes: ValueRef,
-                   align: Align,
-                   flags: MemFlags) {
+pub fn call_memcpy(
+    bx: &Builder<'_, 'll, '_>,
+    dst: &'ll Value,
+    src: &'ll Value,
+    n_bytes: &'ll Value,
+    align: Align,
+    flags: MemFlags,
+) {
     if flags.contains(MemFlags::NONTEMPORAL) {
         // HACK(nox): This is inefficient but there is no nontemporal memcpy.
         let val = bx.load(src, align);
@@ -431,10 +445,10 @@ pub fn call_memcpy(bx: &Builder,
     bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
 }
 
-pub fn memcpy_ty<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    dst: ValueRef,
-    src: ValueRef,
+pub fn memcpy_ty(
+    bx: &Builder<'_, 'll, 'tcx>,
+    dst: &'ll Value,
+    src: &'ll Value,
     layout: TyLayout<'tcx>,
     align: Align,
     flags: MemFlags,
@@ -447,12 +461,14 @@ pub fn memcpy_ty<'a, 'tcx>(
     call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags);
 }
 
-pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                             ptr: ValueRef,
-                             fill_byte: ValueRef,
-                             size: ValueRef,
-                             align: ValueRef,
-                             volatile: bool) -> ValueRef {
+pub fn call_memset(
+    bx: &Builder<'_, 'll, '_>,
+    ptr: &'ll Value,
+    fill_byte: &'ll Value,
+    size: &'ll Value,
+    align: &'ll Value,
+    volatile: bool,
+) -> &'ll Value {
     let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
     let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
     let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
@@ -511,7 +527,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'
     mir::codegen_mir(cx, lldecl, &mir, instance, sig);
 }
 
-pub fn set_link_section(llval: ValueRef, attrs: &CodegenFnAttrs) {
+pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
     let sect = match attrs.link_section {
         Some(name) => name,
         None => return,
@@ -544,17 +560,19 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
 
     let et = cx.sess().entry_fn.get().map(|e| e.2);
     match et {
-        Some(config::EntryMain) => create_entry_fn(cx, span, main_llfn, main_def_id, true),
-        Some(config::EntryStart) => create_entry_fn(cx, span, main_llfn, main_def_id, false),
+        Some(EntryFnType::Main) => create_entry_fn(cx, span, main_llfn, main_def_id, true),
+        Some(EntryFnType::Start) => create_entry_fn(cx, span, main_llfn, main_def_id, false),
         None => {}    // Do nothing.
     }
 
-    fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
-                       sp: Span,
-                       rust_main: ValueRef,
-                       rust_main_def_id: DefId,
-                       use_start_lang_item: bool) {
-        let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], &Type::c_int(cx));
+    fn create_entry_fn(
+        cx: &CodegenCx<'ll, '_>,
+        sp: Span,
+        rust_main: &'ll Value,
+        rust_main_def_id: DefId,
+        use_start_lang_item: bool,
+    ) {
+        let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
 
         let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
         // Given that `main()` has no arguments,
@@ -609,16 +627,14 @@ fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
 }
 
 fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
-                            llmod_id: &str,
+                            llvm_module: &ModuleLlvm,
                             link_meta: &LinkMeta)
-                            -> (ContextRef, ModuleRef, EncodedMetadata) {
+                            -> EncodedMetadata {
     use std::io::Write;
     use flate2::Compression;
     use flate2::write::DeflateEncoder;
 
-    let (metadata_llcx, metadata_llmod) = unsafe {
-        context::create_context_and_module(tcx.sess, llmod_id)
-    };
+    let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod());
 
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
     enum MetadataKind {
@@ -629,26 +645,24 @@ enum MetadataKind {
 
     let kind = tcx.sess.crate_types.borrow().iter().map(|ty| {
         match *ty {
-            config::CrateTypeExecutable |
-            config::CrateTypeStaticlib |
-            config::CrateTypeCdylib => MetadataKind::None,
+            config::CrateType::Executable |
+            config::CrateType::Staticlib |
+            config::CrateType::Cdylib => MetadataKind::None,
 
-            config::CrateTypeRlib => MetadataKind::Uncompressed,
+            config::CrateType::Rlib => MetadataKind::Uncompressed,
 
-            config::CrateTypeDylib |
-            config::CrateTypeProcMacro => MetadataKind::Compressed,
+            config::CrateType::Dylib |
+            config::CrateType::ProcMacro => MetadataKind::Compressed,
         }
     }).max().unwrap_or(MetadataKind::None);
 
     if kind == MetadataKind::None {
-        return (metadata_llcx,
-                metadata_llmod,
-                EncodedMetadata::new());
+        return EncodedMetadata::new();
     }
 
     let metadata = tcx.encode_metadata(link_meta);
     if kind == MetadataKind::Uncompressed {
-        return (metadata_llcx, metadata_llmod, metadata);
+        return metadata;
     }
 
     assert!(kind == MetadataKind::Compressed);
@@ -661,7 +675,7 @@ enum MetadataKind {
     let name = exported_symbols::metadata_symbol_name(tcx);
     let buf = CString::new(name).unwrap();
     let llglobal = unsafe {
-        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr())
+        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
@@ -676,29 +690,27 @@ enum MetadataKind {
         let directive = CString::new(directive).unwrap();
         llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
     }
-    return (metadata_llcx, metadata_llmod, metadata);
+    return metadata;
 }
 
-pub struct ValueIter {
-    cur: ValueRef,
-    step: unsafe extern "C" fn(ValueRef) -> ValueRef,
+pub struct ValueIter<'ll> {
+    cur: Option<&'ll Value>,
+    step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>,
 }
 
-impl Iterator for ValueIter {
-    type Item = ValueRef;
+impl Iterator for ValueIter<'ll> {
+    type Item = &'ll Value;
 
-    fn next(&mut self) -> Option<ValueRef> {
+    fn next(&mut self) -> Option<&'ll Value> {
         let old = self.cur;
-        if !old.is_null() {
+        if let Some(old) = old {
             self.cur = unsafe { (self.step)(old) };
-            Some(old)
-        } else {
-            None
         }
+        old
     }
 }
 
-pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
+pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> {
     unsafe {
         ValueIter {
             cur: llvm::LLVMGetFirstGlobal(llmod),
@@ -730,20 +742,18 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let link_meta = link::build_link_meta(crate_hash);
 
     // Codegen the metadata.
+    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
     let llmod_id = "metadata";
-    let (metadata_llcx, metadata_llmod, metadata) =
-        time(tcx.sess, "write metadata", || {
-            write_metadata(tcx, llmod_id, &link_meta)
-        });
+    let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id);
+    let metadata = time(tcx.sess, "write metadata", || {
+        write_metadata(tcx, &metadata_llvm_module, &link_meta)
+    });
+    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
 
     let metadata_module = ModuleCodegen {
         name: link::METADATA_MODULE_NAME.to_string(),
         llmod_id: llmod_id.to_string(),
-        source: ModuleSource::Codegened(ModuleLlvm {
-            llcx: metadata_llcx,
-            llmod: metadata_llmod,
-            tm: create_target_machine(tcx.sess, false),
-        }),
+        source: ModuleSource::Codegened(metadata_llvm_module),
         kind: ModuleKind::Metadata,
     };
 
@@ -803,13 +813,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
         unsafe {
             let llmod_id = "allocator";
-            let (llcx, llmod) =
-                context::create_context_and_module(tcx.sess, llmod_id);
-            let modules = ModuleLlvm {
-                llmod,
-                llcx,
-                tm: create_target_machine(tcx.sess, false),
-            };
+            let modules = ModuleLlvm::new(tcx.sess, llmod_id);
             time(tcx.sess, "write allocator module", || {
                 allocator::codegen(tcx, &modules, kind)
             });
@@ -1098,7 +1102,7 @@ pub fn new(tcx: TyCtxt) -> CrateInfo {
 
         let load_wasm_items = tcx.sess.crate_types.borrow()
             .iter()
-            .any(|c| *c != config::CrateTypeRlib) &&
+            .any(|c| *c != config::CrateType::Rlib) &&
             tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown";
 
         if load_wasm_items {
@@ -1200,8 +1204,9 @@ fn module_codegen<'a, 'tcx>(
                                    .to_fingerprint().to_hex());
 
         // Instantiate monomorphizations without filling out definitions yet...
-        let cx = CodegenCx::new(tcx, cgu, &llmod_id);
-        let module = {
+        let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
+        let stats = {
+            let cx = CodegenCx::new(tcx, cgu, &llvm_module);
             let mono_items = cx.codegen_unit
                                  .items_in_deterministic_order(cx.tcx);
             for &(mono_item, (linkage, visibility)) in &mono_items {
@@ -1220,7 +1225,7 @@ fn module_codegen<'a, 'tcx>(
             // Run replace-all-uses-with for statics that need it
             for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
                 unsafe {
-                    let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
+                    let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
                     llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
                     llvm::LLVMDeleteGlobal(old_g);
                 }
@@ -1235,7 +1240,7 @@ fn module_codegen<'a, 'tcx>(
 
                 unsafe {
                     let g = llvm::LLVMAddGlobal(cx.llmod,
-                                                val_ty(array).to_ref(),
+                                                val_ty(array),
                                                 name.as_ptr());
                     llvm::LLVMSetInitializer(g, array);
                     llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
@@ -1244,25 +1249,19 @@ fn module_codegen<'a, 'tcx>(
             }
 
             // Finalize debuginfo
-            if cx.sess().opts.debuginfo != NoDebugInfo {
+            if cx.sess().opts.debuginfo != DebugInfo::None {
                 debuginfo::finalize(&cx);
             }
 
-            let llvm_module = ModuleLlvm {
-                llcx: cx.llcx,
-                llmod: cx.llmod,
-                tm: create_target_machine(cx.sess(), false),
-            };
-
-            ModuleCodegen {
-                name: cgu_name,
-                source: ModuleSource::Codegened(llvm_module),
-                kind: ModuleKind::Regular,
-                llmod_id,
-            }
+            cx.stats.into_inner()
         };
 
-        (cx.into_stats(), module)
+        (stats, ModuleCodegen {
+            name: cgu_name,
+            source: ModuleSource::Codegened(llvm_module),
+            kind: ModuleKind::Regular,
+            llmod_id,
+        })
     }
 }
 
index b34d0f1cd9070854c013d58fcfa43c1c7a220570..b174cd8c7ac764d9832858e0dfaf08853afea631 100644 (file)
@@ -8,12 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code)] // FFI wrappers
-
-use llvm;
 use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
-use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef};
-use llvm::{ValueRef, BasicBlockRef, BuilderRef};
+use llvm::{IntPredicate, RealPredicate, False, OperandBundleDef};
+use llvm::{self, BasicBlock};
 use common::*;
 use type_::Type;
 use value::Value;
 use std::ffi::CString;
 use std::ops::Range;
 use std::ptr;
-use syntax_pos::Span;
 
 // All Builders must have an llfn associated with them
 #[must_use]
-pub struct Builder<'a, 'tcx: 'a> {
-    pub llbuilder: BuilderRef,
-    pub cx: &'a CodegenCx<'a, 'tcx>,
+pub struct Builder<'a, 'll: 'a, 'tcx: 'll> {
+    pub llbuilder: &'ll mut llvm::Builder<'ll>,
+    pub cx: &'a CodegenCx<'ll, 'tcx>,
 }
 
-impl<'a, 'tcx> Drop for Builder<'a, 'tcx> {
+impl Drop for Builder<'a, 'll, 'tcx> {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeBuilder(self.llbuilder);
+            llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
         }
     }
 }
@@ -58,8 +54,8 @@ pub struct MemFlags: u8 {
     }
 }
 
-impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self {
+impl Builder<'a, 'll, 'tcx> {
+    pub fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self {
         let bx = Builder::with_cx(cx);
         let llbb = unsafe {
             let name = CString::new(name).unwrap();
@@ -73,7 +69,7 @@ pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str)
         bx
     }
 
-    pub fn with_cx(cx: &'a CodegenCx<'a, 'tcx>) -> Self {
+    pub fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
         // Create a fresh builder from the crate context.
         let llbuilder = unsafe {
             llvm::LLVMCreateBuilderInContext(cx.llcx)
@@ -84,7 +80,7 @@ pub fn with_cx(cx: &'a CodegenCx<'a, 'tcx>) -> Self {
         }
     }
 
-    pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'tcx> {
+    pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'll, 'tcx> {
         Builder::new_block(self.cx, self.llfn(), name)
     }
 
@@ -96,13 +92,13 @@ pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.cx.tcx
     }
 
-    pub fn llfn(&self) -> ValueRef {
+    pub fn llfn(&self) -> &'ll Value {
         unsafe {
             llvm::LLVMGetBasicBlockParent(self.llbb())
         }
     }
 
-    pub fn llbb(&self) -> BasicBlockRef {
+    pub fn llbb(&self) -> &'ll BasicBlock {
         unsafe {
             llvm::LLVMGetInsertBlock(self.llbuilder)
         }
@@ -121,26 +117,20 @@ fn count_insn(&self, category: &str) {
         }
     }
 
-    pub fn set_value_name(&self, value: ValueRef, name: &str) {
+    pub fn set_value_name(&self, value: &'ll Value, name: &str) {
         let cname = CString::new(name.as_bytes()).unwrap();
         unsafe {
             llvm::LLVMSetValueName(value, cname.as_ptr());
         }
     }
 
-    pub fn position_before(&self, insn: ValueRef) {
-        unsafe {
-            llvm::LLVMPositionBuilderBefore(self.llbuilder, insn);
-        }
-    }
-
-    pub fn position_at_end(&self, llbb: BasicBlockRef) {
+    pub fn position_at_end(&self, llbb: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
         }
     }
 
-    pub fn position_at_start(&self, llbb: BasicBlockRef) {
+    pub fn position_at_start(&self, llbb: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
         }
@@ -153,65 +143,57 @@ pub fn ret_void(&self) {
         }
     }
 
-    pub fn ret(&self, v: ValueRef) {
+    pub fn ret(&self, v: &'ll Value) {
         self.count_insn("ret");
         unsafe {
             llvm::LLVMBuildRet(self.llbuilder, v);
         }
     }
 
-    pub fn aggregate_ret(&self, ret_vals: &[ValueRef]) {
-        unsafe {
-            llvm::LLVMBuildAggregateRet(self.llbuilder,
-                                        ret_vals.as_ptr(),
-                                        ret_vals.len() as c_uint);
-        }
-    }
-
-    pub fn br(&self, dest: BasicBlockRef) {
+    pub fn br(&self, dest: &'ll BasicBlock) {
         self.count_insn("br");
         unsafe {
             llvm::LLVMBuildBr(self.llbuilder, dest);
         }
     }
 
-    pub fn cond_br(&self, cond: ValueRef, then_llbb: BasicBlockRef, else_llbb: BasicBlockRef) {
+    pub fn cond_br(
+        &self,
+        cond: &'ll Value,
+        then_llbb: &'ll BasicBlock,
+        else_llbb: &'ll BasicBlock,
+    ) {
         self.count_insn("condbr");
         unsafe {
             llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
         }
     }
 
-    pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: usize) -> ValueRef {
+    pub fn switch(
+        &self,
+        v: &'ll Value,
+        else_llbb: &'ll BasicBlock,
+        num_cases: usize,
+    ) -> &'ll Value {
         unsafe {
             llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
         }
     }
 
-    pub fn indirect_br(&self, addr: ValueRef, num_dests: usize) {
-        self.count_insn("indirectbr");
-        unsafe {
-            llvm::LLVMBuildIndirectBr(self.llbuilder, addr, num_dests as c_uint);
-        }
-    }
-
     pub fn invoke(&self,
-                  llfn: ValueRef,
-                  args: &[ValueRef],
-                  then: BasicBlockRef,
-                  catch: BasicBlockRef,
-                  bundle: Option<&OperandBundleDef>) -> ValueRef {
+                  llfn: &'ll Value,
+                  args: &[&'ll Value],
+                  then: &'ll BasicBlock,
+                  catch: &'ll BasicBlock,
+                  bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value {
         self.count_insn("invoke");
 
-        debug!("Invoke {:?} with args ({})",
-               Value(llfn),
-               args.iter()
-                   .map(|&v| format!("{:?}", Value(v)))
-                   .collect::<Vec<String>>()
-                   .join(", "));
+        debug!("Invoke {:?} with args ({:?})",
+               llfn,
+               args);
 
         let args = self.check_call("invoke", llfn, args);
-        let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
+        let bundle = bundle.map(|b| &*b.raw);
 
         unsafe {
             llvm::LLVMRustBuildInvoke(self.llbuilder,
@@ -233,35 +215,21 @@ pub fn unreachable(&self) {
     }
 
     /* Arithmetic */
-    pub fn add(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("add");
         unsafe {
             llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn nswadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nswadd");
-        unsafe {
-            llvm::LLVMBuildNSWAdd(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn nuwadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nuwadd");
-        unsafe {
-            llvm::LLVMBuildNUWAdd(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn fadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fadd");
         unsafe {
             llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fadd_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fadd");
         unsafe {
             let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
@@ -270,35 +238,21 @@ pub fn fadd_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
         }
     }
 
-    pub fn sub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("sub");
         unsafe {
             llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nswsub");
-        unsafe {
-            llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn nuwsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nuwsub");
-        unsafe {
-            llvm::LLVMBuildNUWSub(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fsub");
         unsafe {
             llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fsub");
         unsafe {
             let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
@@ -307,35 +261,21 @@ pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
         }
     }
 
-    pub fn mul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("mul");
         unsafe {
             llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn nswmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nswmul");
-        unsafe {
-            llvm::LLVMBuildNSWMul(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn nuwmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nuwmul");
-        unsafe {
-            llvm::LLVMBuildNUWMul(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn fmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fmul");
         unsafe {
             llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fmul_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fmul");
         unsafe {
             let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
@@ -345,42 +285,42 @@ pub fn fmul_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
     }
 
 
-    pub fn udiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("udiv");
         unsafe {
             llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn exactudiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn exactudiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("exactudiv");
         unsafe {
             llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn sdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("sdiv");
         unsafe {
             llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn exactsdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn exactsdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("exactsdiv");
         unsafe {
             llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fdiv");
         unsafe {
             llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn fdiv_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fdiv");
         unsafe {
             let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
@@ -389,28 +329,28 @@ pub fn fdiv_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
         }
     }
 
-    pub fn urem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("urem");
         unsafe {
             llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn srem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn srem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("srem");
         unsafe {
             llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn frem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn frem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("frem");
         unsafe {
             llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn frem_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("frem");
         unsafe {
             let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
@@ -419,91 +359,70 @@ pub fn frem_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
         }
     }
 
-    pub fn shl(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("shl");
         unsafe {
             llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn lshr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn lshr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("lshr");
         unsafe {
             llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn ashr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn ashr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("ashr");
         unsafe {
             llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn and(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn and(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("and");
         unsafe {
             llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn or(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn or(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("or");
         unsafe {
             llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn xor(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn xor(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("xor");
         unsafe {
             llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
         }
     }
 
-    pub fn binop(&self, op: Opcode, lhs: ValueRef, rhs: ValueRef)
-              -> ValueRef {
-        self.count_insn("binop");
-        unsafe {
-            llvm::LLVMBuildBinOp(self.llbuilder, op, lhs, rhs, noname())
-        }
-    }
-
-    pub fn neg(&self, v: ValueRef) -> ValueRef {
+    pub fn neg(&self, v: &'ll Value) -> &'ll Value {
         self.count_insn("neg");
         unsafe {
             llvm::LLVMBuildNeg(self.llbuilder, v, noname())
         }
     }
 
-    pub fn nswneg(&self, v: ValueRef) -> ValueRef {
-        self.count_insn("nswneg");
-        unsafe {
-            llvm::LLVMBuildNSWNeg(self.llbuilder, v, noname())
-        }
-    }
-
-    pub fn nuwneg(&self, v: ValueRef) -> ValueRef {
-        self.count_insn("nuwneg");
-        unsafe {
-            llvm::LLVMBuildNUWNeg(self.llbuilder, v, noname())
-        }
-    }
-    pub fn fneg(&self, v: ValueRef) -> ValueRef {
+    pub fn fneg(&self, v: &'ll Value) -> &'ll Value {
         self.count_insn("fneg");
         unsafe {
             llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
         }
     }
 
-    pub fn not(&self, v: ValueRef) -> ValueRef {
+    pub fn not(&self, v: &'ll Value) -> &'ll Value {
         self.count_insn("not");
         unsafe {
             llvm::LLVMBuildNot(self.llbuilder, v, noname())
         }
     }
 
-    pub fn alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
+    pub fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
         let bx = Builder::with_cx(self.cx);
         bx.position_at_start(unsafe {
             llvm::LLVMGetFirstBasicBlock(self.llfn())
@@ -511,14 +430,14 @@ pub fn alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
         bx.dynamic_alloca(ty, name, align)
     }
 
-    pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
+    pub fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
         self.count_insn("alloca");
         unsafe {
             let alloca = if name.is_empty() {
-                llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
+                llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
             } else {
                 let name = CString::new(name).unwrap();
-                llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
+                llvm::LLVMBuildAlloca(self.llbuilder, ty,
                                       name.as_ptr())
             };
             llvm::LLVMSetAlignment(alloca, align.abi() as c_uint);
@@ -526,14 +445,7 @@ pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef {
         }
     }
 
-    pub fn free(&self, ptr: ValueRef) {
-        self.count_insn("free");
-        unsafe {
-            llvm::LLVMBuildFree(self.llbuilder, ptr);
-        }
-    }
-
-    pub fn load(&self, ptr: ValueRef, align: Align) -> ValueRef {
+    pub fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value {
         self.count_insn("load");
         unsafe {
             let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
@@ -542,7 +454,7 @@ pub fn load(&self, ptr: ValueRef, align: Align) -> ValueRef {
         }
     }
 
-    pub fn volatile_load(&self, ptr: ValueRef) -> ValueRef {
+    pub fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value {
         self.count_insn("load.volatile");
         unsafe {
             let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
@@ -551,7 +463,7 @@ pub fn volatile_load(&self, ptr: ValueRef) -> ValueRef {
         }
     }
 
-    pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering, align: Align) -> ValueRef {
+    pub fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, align: Align) -> &'ll Value {
         self.count_insn("load.atomic");
         unsafe {
             let load = llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order);
@@ -564,7 +476,7 @@ pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering, align: Align) ->
     }
 
 
-    pub fn range_metadata(&self, load: ValueRef, range: Range<u128>) {
+    pub fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
         unsafe {
             let llty = val_ty(load);
             let v = [
@@ -579,26 +491,25 @@ pub fn range_metadata(&self, load: ValueRef, range: Range<u128>) {
         }
     }
 
-    pub fn nonnull_metadata(&self, load: ValueRef) {
+    pub fn nonnull_metadata(&self, load: &'ll Value) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
         }
     }
 
-    pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef {
+    pub fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
         self.store_with_flags(val, ptr, align, MemFlags::empty())
     }
 
     pub fn store_with_flags(
         &self,
-        val: ValueRef,
-        ptr: ValueRef,
+        val: &'ll Value,
+        ptr: &'ll Value,
         align: Align,
         flags: MemFlags,
-    ) -> ValueRef {
-        debug!("Store {:?} -> {:?} ({:?})", Value(val), Value(ptr), flags);
-        assert!(!self.llbuilder.is_null());
+    ) -> &'ll Value {
+        debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
         self.count_insn("store");
         let ptr = self.check_store(val, ptr);
         unsafe {
@@ -625,9 +536,9 @@ pub fn store_with_flags(
         }
     }
 
-    pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef,
+    pub fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value,
                         order: AtomicOrdering, align: Align) {
-        debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
+        debug!("Store {:?} -> {:?}", val, ptr);
         self.count_insn("store.atomic");
         let ptr = self.check_store(val, ptr);
         unsafe {
@@ -638,7 +549,7 @@ pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef,
         }
     }
 
-    pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
+    pub fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
         self.count_insn("gep");
         unsafe {
             llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
@@ -646,7 +557,7 @@ pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
         }
     }
 
-    pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
+    pub fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
         self.count_insn("inboundsgep");
         unsafe {
             llvm::LLVMBuildInBoundsGEP(
@@ -654,7 +565,7 @@ pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
         }
     }
 
-    pub fn struct_gep(&self, ptr: ValueRef, idx: u64) -> ValueRef {
+    pub fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value {
         self.count_insn("structgep");
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
@@ -662,164 +573,114 @@ pub fn struct_gep(&self, ptr: ValueRef, idx: u64) -> ValueRef {
         }
     }
 
-    pub fn global_string(&self, _str: *const c_char) -> ValueRef {
-        self.count_insn("globalstring");
-        unsafe {
-            llvm::LLVMBuildGlobalString(self.llbuilder, _str, noname())
-        }
-    }
-
-    pub fn global_string_ptr(&self, _str: *const c_char) -> ValueRef {
-        self.count_insn("globalstringptr");
-        unsafe {
-            llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _str, noname())
-        }
-    }
-
     /* Casts */
-    pub fn trunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("trunc");
         unsafe {
-            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn zext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("zext");
         unsafe {
-            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn sext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("sext");
         unsafe {
-            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fptoui(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fptoui");
         unsafe {
-            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fptosi(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fptosi");
         unsafe {
-            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty.to_ref(),noname())
+            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
         }
     }
 
-    pub fn uitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("uitofp");
         unsafe {
-            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn sitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("sitofp");
         unsafe {
-            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fptrunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fptrunc");
         unsafe {
-            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn fpext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("fpext");
         unsafe {
-            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn ptrtoint(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("ptrtoint");
         unsafe {
-            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn inttoptr(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("inttoptr");
         unsafe {
-            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("bitcast");
         unsafe {
-            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn zext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("zextorbitcast");
-        unsafe {
-            llvm::LLVMBuildZExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn sext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("sextorbitcast");
-        unsafe {
-            llvm::LLVMBuildSExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn trunc_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("truncorbitcast");
-        unsafe {
-            llvm::LLVMBuildTruncOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn cast(&self, op: Opcode, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("cast");
-        unsafe {
-            llvm::LLVMBuildCast(self.llbuilder, op, val, dest_ty.to_ref(), noname())
-        }
-    }
-
-    pub fn pointercast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
+    pub fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("pointercast");
         unsafe {
-            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
         }
     }
 
-    pub fn intcast(&self, val: ValueRef, dest_ty: Type, is_signed: bool) -> ValueRef {
+    pub fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
         self.count_insn("intcast");
         unsafe {
-            llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty.to_ref(), is_signed)
-        }
-    }
-
-    pub fn fpcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
-        self.count_insn("fpcast");
-        unsafe {
-            llvm::LLVMBuildFPCast(self.llbuilder, val, dest_ty.to_ref(), noname())
+            llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
         }
     }
 
-
     /* Comparisons */
-    pub fn icmp(&self, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("icmp");
         unsafe {
             llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
         }
     }
 
-    pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("fcmp");
         unsafe {
             llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
@@ -827,14 +688,14 @@ pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef
     }
 
     /* Miscellaneous instructions */
-    pub fn empty_phi(&self, ty: Type) -> ValueRef {
+    pub fn empty_phi(&self, ty: &'ll Type) -> &'ll Value {
         self.count_insn("emptyphi");
         unsafe {
-            llvm::LLVMBuildPhi(self.llbuilder, ty.to_ref(), noname())
+            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
         }
     }
 
-    pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef {
+    pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
         assert_eq!(vals.len(), bbs.len());
         let phi = self.empty_phi(ty);
         self.count_insn("addincoming");
@@ -846,36 +707,10 @@ pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRe
         }
     }
 
-    pub fn add_span_comment(&self, sp: Span, text: &str) {
-        if self.cx.sess().asm_comments() {
-            let s = format!("{} ({})",
-                            text,
-                            self.cx.sess().codemap().span_to_string(sp));
-            debug!("{}", s);
-            self.add_comment(&s);
-        }
-    }
-
-    pub fn add_comment(&self, text: &str) {
-        if self.cx.sess().asm_comments() {
-            let sanitized = text.replace("$", "");
-            let comment_text = format!("{} {}", "#",
-                                       sanitized.replace("\n", "\n\t# "));
-            self.count_insn("inlineasm");
-            let comment_text = CString::new(comment_text).unwrap();
-            let asm = unsafe {
-                llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.cx)).to_ref(),
-                                         comment_text.as_ptr(), noname(), False,
-                                         False)
-            };
-            self.call(asm, &[], None);
-        }
-    }
-
     pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
-                         inputs: &[ValueRef], output: Type,
+                         inputs: &[&'ll Value], output: &'ll Type,
                          volatile: bool, alignstack: bool,
-                         dia: AsmDialect) -> ValueRef {
+                         dia: AsmDialect) -> &'ll Value {
         self.count_insn("inlineasm");
 
         let volatile = if volatile { llvm::True }
@@ -884,32 +719,29 @@ pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
                          else          { llvm::False };
 
         let argtys = inputs.iter().map(|v| {
-            debug!("Asm Input Type: {:?}", Value(*v));
+            debug!("Asm Input Type: {:?}", *v);
             val_ty(*v)
         }).collect::<Vec<_>>();
 
         debug!("Asm Output Type: {:?}", output);
-        let fty = Type::func(&argtys[..], &output);
+        let fty = Type::func(&argtys[..], output);
         unsafe {
             let v = llvm::LLVMRustInlineAsm(
-                fty.to_ref(), asm, cons, volatile, alignstack, dia);
+                fty, asm, cons, volatile, alignstack, dia);
             self.call(v, inputs, None)
         }
     }
 
-    pub fn call(&self, llfn: ValueRef, args: &[ValueRef],
-                bundle: Option<&OperandBundleDef>) -> ValueRef {
+    pub fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
+                bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value {
         self.count_insn("call");
 
-        debug!("Call {:?} with args ({})",
-               Value(llfn),
-               args.iter()
-                   .map(|&v| format!("{:?}", Value(v)))
-                   .collect::<Vec<String>>()
-                   .join(", "));
+        debug!("Call {:?} with args ({:?})",
+               llfn,
+               args);
 
         let args = self.check_call("call", llfn, args);
-        let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
+        let bundle = bundle.map(|b| &*b.raw);
 
         unsafe {
             llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(),
@@ -917,214 +749,182 @@ pub fn call(&self, llfn: ValueRef, args: &[ValueRef],
         }
     }
 
-    pub fn minnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("minnum");
         unsafe {
             let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs);
-            if instr.is_null() {
-                bug!("LLVMRustBuildMinNum is not available in LLVM version < 6.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0")
         }
     }
-    pub fn maxnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+    pub fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("maxnum");
         unsafe {
             let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs);
-            if instr.is_null() {
-                bug!("LLVMRustBuildMaxNum is not available in LLVM version < 6.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0")
         }
     }
 
-    pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef {
+    pub fn select(
+        &self, cond: &'ll Value,
+        then_val: &'ll Value,
+        else_val: &'ll Value,
+    ) -> &'ll Value {
         self.count_insn("select");
         unsafe {
             llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
         }
     }
 
-    pub fn va_arg(&self, list: ValueRef, ty: Type) -> ValueRef {
+    #[allow(dead_code)]
+    pub fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
         self.count_insn("vaarg");
         unsafe {
-            llvm::LLVMBuildVAArg(self.llbuilder, list, ty.to_ref(), noname())
+            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
         }
     }
 
-    pub fn extract_element(&self, vec: ValueRef, idx: ValueRef) -> ValueRef {
+    pub fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
         self.count_insn("extractelement");
         unsafe {
             llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
         }
     }
 
-    pub fn insert_element(&self, vec: ValueRef, elt: ValueRef, idx: ValueRef) -> ValueRef {
+    pub fn insert_element(
+        &self, vec: &'ll Value,
+        elt: &'ll Value,
+        idx: &'ll Value,
+    ) -> &'ll Value {
         self.count_insn("insertelement");
         unsafe {
             llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
         }
     }
 
-    pub fn shuffle_vector(&self, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef {
+    pub fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value {
         self.count_insn("shufflevector");
         unsafe {
             llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
         }
     }
 
-    pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef {
+    pub fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
         unsafe {
             let elt_ty = val_ty(elt);
-            let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
+            let undef = llvm::LLVMGetUndef(Type::vector(elt_ty, num_elts as u64));
             let vec = self.insert_element(undef, elt, C_i32(self.cx, 0));
-            let vec_i32_ty = Type::vector(&Type::i32(self.cx), num_elts as u64);
+            let vec_i32_ty = Type::vector(Type::i32(self.cx), num_elts as u64);
             self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
         }
     }
 
-    pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fadd_fast");
         unsafe {
             // FIXME: add a non-fast math version once
             // https://bugs.llvm.org/show_bug.cgi?id=36732
             // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src)
+                .expect("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmul_fast");
         unsafe {
             // FIXME: add a non-fast math version once
             // https://bugs.llvm.org/show_bug.cgi?id=36732
             // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src)
+                .expect("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.add");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.mul");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.and");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.or");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.xor");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmin");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmax");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmin_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true)
+                .expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
+    pub fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmax_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
-            }
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true)
+                .expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
-    pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+    pub fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
         self.count_insn("vector.reduce.min");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0")
         }
     }
-    pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+    pub fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
         self.count_insn("vector.reduce.max");
         unsafe {
             let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed);
-            if instr.is_null() {
-                bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0");
-            }
-            instr
+            instr.expect("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0")
         }
     }
 
-    pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef {
+    pub fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
         self.count_insn("extractvalue");
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
@@ -1132,8 +932,8 @@ pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef {
         }
     }
 
-    pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
-                       idx: u64) -> ValueRef {
+    pub fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value,
+                       idx: u64) -> &'ll Value {
         self.count_insn("insertvalue");
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
@@ -1142,50 +942,29 @@ pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
         }
     }
 
-    pub fn is_null(&self, val: ValueRef) -> ValueRef {
-        self.count_insn("isnull");
-        unsafe {
-            llvm::LLVMBuildIsNull(self.llbuilder, val, noname())
-        }
-    }
-
-    pub fn is_not_null(&self, val: ValueRef) -> ValueRef {
-        self.count_insn("isnotnull");
-        unsafe {
-            llvm::LLVMBuildIsNotNull(self.llbuilder, val, noname())
-        }
-    }
-
-    pub fn ptrdiff(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("ptrdiff");
-        unsafe {
-            llvm::LLVMBuildPtrDiff(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef,
-                       num_clauses: usize) -> ValueRef {
+    pub fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value,
+                       num_clauses: usize) -> &'ll Value {
         self.count_insn("landingpad");
         unsafe {
-            llvm::LLVMBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
+            llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
                                       num_clauses as c_uint, noname())
         }
     }
 
-    pub fn add_clause(&self, landing_pad: ValueRef, clause: ValueRef) {
+    pub fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) {
         unsafe {
             llvm::LLVMAddClause(landing_pad, clause);
         }
     }
 
-    pub fn set_cleanup(&self, landing_pad: ValueRef) {
+    pub fn set_cleanup(&self, landing_pad: &'ll Value) {
         self.count_insn("setcleanup");
         unsafe {
             llvm::LLVMSetCleanup(landing_pad, llvm::True);
         }
     }
 
-    pub fn resume(&self, exn: ValueRef) -> ValueRef {
+    pub fn resume(&self, exn: &'ll Value) -> &'ll Value {
         self.count_insn("resume");
         unsafe {
             llvm::LLVMBuildResume(self.llbuilder, exn)
@@ -1193,10 +972,9 @@ pub fn resume(&self, exn: ValueRef) -> ValueRef {
     }
 
     pub fn cleanup_pad(&self,
-                       parent: Option<ValueRef>,
-                       args: &[ValueRef]) -> ValueRef {
+                       parent: Option<&'ll Value>,
+                       args: &[&'ll Value]) -> &'ll Value {
         self.count_insn("cleanuppad");
-        let parent = parent.unwrap_or(ptr::null_mut());
         let name = CString::new("cleanuppad").unwrap();
         let ret = unsafe {
             llvm::LLVMRustBuildCleanupPad(self.llbuilder,
@@ -1205,24 +983,23 @@ pub fn cleanup_pad(&self,
                                           args.as_ptr(),
                                           name.as_ptr())
         };
-        assert!(!ret.is_null(), "LLVM does not have support for cleanuppad");
-        return ret
+        ret.expect("LLVM does not have support for cleanuppad")
     }
 
-    pub fn cleanup_ret(&self, cleanup: ValueRef,
-                       unwind: Option<BasicBlockRef>) -> ValueRef {
+    pub fn cleanup_ret(
+        &self, cleanup: &'ll Value,
+        unwind: Option<&'ll BasicBlock>,
+    ) -> &'ll Value {
         self.count_insn("cleanupret");
-        let unwind = unwind.unwrap_or(ptr::null_mut());
         let ret = unsafe {
             llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind)
         };
-        assert!(!ret.is_null(), "LLVM does not have support for cleanupret");
-        return ret
+        ret.expect("LLVM does not have support for cleanupret")
     }
 
     pub fn catch_pad(&self,
-                     parent: ValueRef,
-                     args: &[ValueRef]) -> ValueRef {
+                     parent: &'ll Value,
+                     args: &[&'ll Value]) -> &'ll Value {
         self.count_insn("catchpad");
         let name = CString::new("catchpad").unwrap();
         let ret = unsafe {
@@ -1230,62 +1007,67 @@ pub fn catch_pad(&self,
                                         args.len() as c_uint, args.as_ptr(),
                                         name.as_ptr())
         };
-        assert!(!ret.is_null(), "LLVM does not have support for catchpad");
-        return ret
+        ret.expect("LLVM does not have support for catchpad")
     }
 
-    pub fn catch_ret(&self, pad: ValueRef, unwind: BasicBlockRef) -> ValueRef {
+    pub fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value {
         self.count_insn("catchret");
         let ret = unsafe {
             llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind)
         };
-        assert!(!ret.is_null(), "LLVM does not have support for catchret");
-        return ret
+        ret.expect("LLVM does not have support for catchret")
     }
 
-    pub fn catch_switch(&self,
-                        parent: Option<ValueRef>,
-                        unwind: Option<BasicBlockRef>,
-                        num_handlers: usize) -> ValueRef {
+    pub fn catch_switch(
+        &self,
+        parent: Option<&'ll Value>,
+        unwind: Option<&'ll BasicBlock>,
+        num_handlers: usize,
+    ) -> &'ll Value {
         self.count_insn("catchswitch");
-        let parent = parent.unwrap_or(ptr::null_mut());
-        let unwind = unwind.unwrap_or(ptr::null_mut());
         let name = CString::new("catchswitch").unwrap();
         let ret = unsafe {
             llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
                                            num_handlers as c_uint,
                                            name.as_ptr())
         };
-        assert!(!ret.is_null(), "LLVM does not have support for catchswitch");
-        return ret
+        ret.expect("LLVM does not have support for catchswitch")
     }
 
-    pub fn add_handler(&self, catch_switch: ValueRef, handler: BasicBlockRef) {
+    pub fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMRustAddHandler(catch_switch, handler);
         }
     }
 
-    pub fn set_personality_fn(&self, personality: ValueRef) {
+    pub fn set_personality_fn(&self, personality: &'ll Value) {
         unsafe {
             llvm::LLVMSetPersonalityFn(self.llfn(), personality);
         }
     }
 
     // Atomic Operations
-    pub fn atomic_cmpxchg(&self, dst: ValueRef,
-                         cmp: ValueRef, src: ValueRef,
-                         order: AtomicOrdering,
-                         failure_order: AtomicOrdering,
-                         weak: llvm::Bool) -> ValueRef {
+    pub fn atomic_cmpxchg(
+        &self,
+        dst: &'ll Value,
+        cmp: &'ll Value,
+        src: &'ll Value,
+        order: AtomicOrdering,
+        failure_order: AtomicOrdering,
+        weak: llvm::Bool,
+    ) -> &'ll Value {
         unsafe {
             llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
                                          order, failure_order, weak)
         }
     }
-    pub fn atomic_rmw(&self, op: AtomicRmwBinOp,
-                     dst: ValueRef, src: ValueRef,
-                     order: AtomicOrdering) -> ValueRef {
+    pub fn atomic_rmw(
+        &self,
+        op: AtomicRmwBinOp,
+        dst: &'ll Value,
+        src: &'ll Value,
+        order: AtomicOrdering,
+    ) -> &'ll Value {
         unsafe {
             llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order, False)
         }
@@ -1297,20 +1079,20 @@ pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
         }
     }
 
-    pub fn add_case(&self, s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) {
+    pub fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMAddCase(s, on_val, dest)
         }
     }
 
-    pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
+    pub fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
         self.count_insn("addincoming");
         unsafe {
             llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
         }
     }
 
-    pub fn set_invariant_load(&self, load: ValueRef) {
+    pub fn set_invariant_load(&self, load: &'ll Value) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
@@ -1319,8 +1101,8 @@ pub fn set_invariant_load(&self, load: ValueRef) {
 
     /// Returns the ptr value that should be used for storing `val`.
     fn check_store<'b>(&self,
-                       val: ValueRef,
-                       ptr: ValueRef) -> ValueRef {
+                       val: &'ll Value,
+                       ptr: &'ll Value) -> &'ll Value {
         let dest_ptr_ty = val_ty(ptr);
         let stored_ty = val_ty(val);
         let stored_ptr_ty = stored_ty.ptr_to();
@@ -1340,8 +1122,8 @@ fn check_store<'b>(&self,
     /// Returns the args that should be used for a call to `llfn`.
     fn check_call<'b>(&self,
                       typ: &str,
-                      llfn: ValueRef,
-                      args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
+                      llfn: &'ll Value,
+                      args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
         let mut fn_ty = val_ty(llfn);
         // Strip off pointers
         while fn_ty.kind() == llvm::TypeKind::Pointer {
@@ -1369,8 +1151,7 @@ fn check_call<'b>(&self,
                 if expected_ty != actual_ty {
                     debug!("Type mismatch in function call of {:?}. \
                             Expected {:?} for param {}, got {:?}; injecting bitcast",
-                           Value(llfn),
-                           expected_ty, i, actual_ty);
+                           llfn, expected_ty, i, actual_ty);
                     self.bitcast(actual_val, expected_ty)
                 } else {
                     actual_val
@@ -1381,11 +1162,11 @@ fn check_call<'b>(&self,
         return Cow::Owned(casted_args);
     }
 
-    pub fn lifetime_start(&self, ptr: ValueRef, size: Size) {
+    pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) {
         self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size);
     }
 
-    pub fn lifetime_end(&self, ptr: ValueRef, size: Size) {
+    pub fn lifetime_end(&self, ptr: &'ll Value, size: Size) {
         self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size);
     }
 
@@ -1397,7 +1178,7 @@ pub fn lifetime_end(&self, ptr: ValueRef, size: Size) {
     ///
     /// If LLVM lifetime intrinsic support is disabled (i.e.  optimizations
     /// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
-    fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: ValueRef, size: Size) {
+    fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) {
         if self.cx.sess().opts.optimize == config::OptLevel::No {
             return;
         }
index 2c01bd42cc77a4dee0b5d6dd7cdeb4151b1db5b6..3594351802fe91cabf67112f5c7b2f6ebae108ba 100644 (file)
 use common::{self, CodegenCx};
 use consts;
 use declare;
-use llvm::{self, ValueRef};
+use llvm;
 use monomorphize::Instance;
 use type_of::LayoutLlvmExt;
+use value::Value;
 
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TypeFoldable};
 ///
 /// - `cx`: the crate context
 /// - `instance`: the instance to be instantiated
-pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                        instance: Instance<'tcx>)
-                        -> ValueRef
-{
+pub fn get_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    instance: Instance<'tcx>,
+) -> &'ll Value {
     let tcx = cx.tcx;
 
     debug!("get_fn(instance={:?})", instance);
@@ -132,7 +133,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 // This is a monomorphization. Its expected visibility depends
                 // on whether we are in share-generics mode.
 
-                if cx.tcx.share_generics() {
+                if cx.tcx.sess.opts.share_generics() {
                     // We are in share_generics mode.
 
                     if instance_def_id.is_local() {
@@ -204,11 +205,11 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     llfn
 }
 
-pub fn resolve_and_get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    def_id: DefId,
-                                    substs: &'tcx Substs<'tcx>)
-                                    -> ValueRef
-{
+pub fn resolve_and_get_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    def_id: DefId,
+    substs: &'tcx Substs<'tcx>,
+) -> &'ll Value {
     get_fn(
         cx,
         ty::Instance::resolve(
index 60bba635a7887bbe48fb81a5759eb8bca833fb13..51fc610408b5213538dc7f2ce8c6fa5aa6df8ff5 100644 (file)
@@ -12,8 +12,7 @@
 
 //! Code that is useful in various codegen modules.
 
-use llvm;
-use llvm::{ValueRef, ContextRef, TypeKind};
+use llvm::{self, TypeKind};
 use llvm::{True, False, Bool, OperandBundleDef};
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::LangItem;
@@ -25,6 +24,7 @@
 use type_::Type;
 use type_of::LayoutLlvmExt;
 use value::Value;
+
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{HasDataLayout, LayoutOf};
 use rustc::hir;
@@ -90,83 +90,83 @@ pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bo
 /// When inside of a landing pad, each function call in LLVM IR needs to be
 /// annotated with which landing pad it's a part of. This is accomplished via
 /// the `OperandBundleDef` value created for MSVC landing pads.
-pub struct Funclet {
-    cleanuppad: ValueRef,
-    operand: OperandBundleDef,
+pub struct Funclet<'ll> {
+    cleanuppad: &'ll Value,
+    operand: OperandBundleDef<'ll>,
 }
 
-impl Funclet {
-    pub fn new(cleanuppad: ValueRef) -> Funclet {
+impl Funclet<'ll> {
+    pub fn new(cleanuppad: &'ll Value) -> Self {
         Funclet {
             cleanuppad,
             operand: OperandBundleDef::new("funclet", &[cleanuppad]),
         }
     }
 
-    pub fn cleanuppad(&self) -> ValueRef {
+    pub fn cleanuppad(&self) -> &'ll Value {
         self.cleanuppad
     }
 
-    pub fn bundle(&self) -> &OperandBundleDef {
+    pub fn bundle(&self) -> &OperandBundleDef<'ll> {
         &self.operand
     }
 }
 
-pub fn val_ty(v: ValueRef) -> Type {
+pub fn val_ty(v: &'ll Value) -> &'ll Type {
     unsafe {
-        Type::from_ref(llvm::LLVMTypeOf(v))
+        llvm::LLVMTypeOf(v)
     }
 }
 
 // LLVM constant constructors.
-pub fn C_null(t: Type) -> ValueRef {
+pub fn C_null(t: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstNull(t.to_ref())
+        llvm::LLVMConstNull(t)
     }
 }
 
-pub fn C_undef(t: Type) -> ValueRef {
+pub fn C_undef(t: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMGetUndef(t.to_ref())
+        llvm::LLVMGetUndef(t)
     }
 }
 
-pub fn C_int(t: Type, i: i64) -> ValueRef {
+pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstInt(t.to_ref(), i as u64, True)
+        llvm::LLVMConstInt(t, i as u64, True)
     }
 }
 
-pub fn C_uint(t: Type, i: u64) -> ValueRef {
+pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstInt(t.to_ref(), i, False)
+        llvm::LLVMConstInt(t, i, False)
     }
 }
 
-pub fn C_uint_big(t: Type, u: u128) -> ValueRef {
+pub fn C_uint_big(t: &'ll Type, u: u128) -> &'ll Value {
     unsafe {
         let words = [u as u64, (u >> 64) as u64];
-        llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr())
+        llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
     }
 }
 
-pub fn C_bool(cx: &CodegenCx, val: bool) -> ValueRef {
+pub fn C_bool(cx: &CodegenCx<'ll, '_>, val: bool) -> &'ll Value {
     C_uint(Type::i1(cx), val as u64)
 }
 
-pub fn C_i32(cx: &CodegenCx, i: i32) -> ValueRef {
+pub fn C_i32(cx: &CodegenCx<'ll, '_>, i: i32) -> &'ll Value {
     C_int(Type::i32(cx), i as i64)
 }
 
-pub fn C_u32(cx: &CodegenCx, i: u32) -> ValueRef {
+pub fn C_u32(cx: &CodegenCx<'ll, '_>, i: u32) -> &'ll Value {
     C_uint(Type::i32(cx), i as u64)
 }
 
-pub fn C_u64(cx: &CodegenCx, i: u64) -> ValueRef {
+pub fn C_u64(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
     C_uint(Type::i64(cx), i)
 }
 
-pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef {
+pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
     let bit_size = cx.data_layout().pointer_size.bits();
     if bit_size < 64 {
         // make sure it doesn't overflow
@@ -176,14 +176,18 @@ pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef {
     C_uint(cx.isize_ty, i)
 }
 
-pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef {
+pub fn C_u8(cx: &CodegenCx<'ll, '_>, i: u8) -> &'ll Value {
     C_uint(Type::i8(cx), i as u64)
 }
 
 
 // This is a 'c-like' raw string, which differs from
 // our boxed-and-length-annotated strings.
-pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef {
+pub fn C_cstr(
+    cx: &CodegenCx<'ll, '_>,
+    s: LocalInternedString,
+    null_terminated: bool,
+) -> &'ll Value {
     unsafe {
         if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
             return llval;
@@ -208,24 +212,28 @@ pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) ->
 
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef {
+pub fn C_str_slice(cx: &CodegenCx<'ll, '_>, s: LocalInternedString) -> &'ll Value {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
         cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
     C_fat_ptr(cx, cs, C_usize(cx, len as u64))
 }
 
-pub fn C_fat_ptr(cx: &CodegenCx, ptr: ValueRef, meta: ValueRef) -> ValueRef {
+pub fn C_fat_ptr(cx: &CodegenCx<'ll, '_>, ptr: &'ll Value, meta: &'ll Value) -> &'ll Value {
     assert_eq!(abi::FAT_PTR_ADDR, 0);
     assert_eq!(abi::FAT_PTR_EXTRA, 1);
     C_struct(cx, &[ptr, meta], false)
 }
 
-pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef {
+pub fn C_struct(cx: &CodegenCx<'ll, '_>, elts: &[&'ll Value], packed: bool) -> &'ll Value {
     C_struct_in_context(cx.llcx, elts, packed)
 }
 
-pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
+pub fn C_struct_in_context(
+    llcx: &'ll llvm::Context,
+    elts: &[&'ll Value],
+    packed: bool,
+) -> &'ll Value {
     unsafe {
         llvm::LLVMConstStructInContext(llcx,
                                        elts.as_ptr(), elts.len() as c_uint,
@@ -233,47 +241,47 @@ pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) ->
     }
 }
 
-pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
+pub fn C_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
     unsafe {
-        return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
+        return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
     }
 }
 
-pub fn C_vector(elts: &[ValueRef]) -> ValueRef {
+pub fn C_vector(elts: &[&'ll Value]) -> &'ll Value {
     unsafe {
         return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
     }
 }
 
-pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef {
+pub fn C_bytes(cx: &CodegenCx<'ll, '_>, bytes: &[u8]) -> &'ll Value {
     C_bytes_in_context(cx.llcx, bytes)
 }
 
-pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
+pub fn C_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
     unsafe {
         let ptr = bytes.as_ptr() as *const c_char;
         return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
     }
 }
 
-pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef {
+pub fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
     unsafe {
         assert_eq!(idx as c_uint as u64, idx);
         let us = &[idx as c_uint];
         let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
 
         debug!("const_get_elt(v={:?}, idx={}, r={:?})",
-               Value(v), idx, Value(r));
+               v, idx, r);
 
         r
     }
 }
 
-pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
+pub fn const_get_real(v: &'ll Value) -> Option<(f64, bool)> {
     unsafe {
         if is_const_real(v) {
             let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
-            let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool);
+            let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
             let loses_info = if loses_info == 1 { true } else { false };
             Some((r, loses_info))
         } else {
@@ -282,21 +290,21 @@ pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
     }
 }
 
-pub fn const_to_uint(v: ValueRef) -> u64 {
+pub fn const_to_uint(v: &'ll Value) -> u64 {
     unsafe {
         llvm::LLVMConstIntGetZExtValue(v)
     }
 }
 
-pub fn is_const_integral(v: ValueRef) -> bool {
+pub fn is_const_integral(v: &'ll Value) -> bool {
     unsafe {
-        !llvm::LLVMIsAConstantInt(v).is_null()
+        llvm::LLVMIsAConstantInt(v).is_some()
     }
 }
 
-pub fn is_const_real(v: ValueRef) -> bool {
+pub fn is_const_real(v: &'ll Value) -> bool {
     unsafe {
-        !llvm::LLVMIsAConstantFP(v).is_null()
+        llvm::LLVMIsAConstantFP(v).is_some()
     }
 }
 
@@ -306,12 +314,12 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
     ((hi as u128) << 64) | (lo as u128)
 }
 
-pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option<u128> {
+pub fn const_to_opt_u128(v: &'ll Value, sign_ext: bool) -> Option<u128> {
     unsafe {
         if is_const_integral(v) {
             let (mut lo, mut hi) = (0u64, 0u64);
             let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
-                                                       &mut hi as *mut u64, &mut lo as *mut u64);
+                                                       &mut hi, &mut lo);
             if success {
                 Some(hi_lo_to_u128(lo, hi))
             } else {
@@ -345,20 +353,20 @@ pub fn langcall(tcx: TyCtxt,
 // all shifts). For 32- and 64-bit types, this matches the semantics
 // of Java. (See related discussion on #1877 and #10183.)
 
-pub fn build_unchecked_lshift<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    lhs: ValueRef,
-    rhs: ValueRef
-) -> ValueRef {
+pub fn build_unchecked_lshift(
+    bx: &Builder<'a, 'll, 'tcx>,
+    lhs: &'ll Value,
+    rhs: &'ll Value
+) -> &'ll Value {
     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bx, rhs);
     bx.shl(lhs, rhs)
 }
 
-pub fn build_unchecked_rshift<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef
-) -> ValueRef {
+pub fn build_unchecked_rshift(
+    bx: &Builder<'a, 'll, 'tcx>, lhs_t: Ty<'tcx>, lhs: &'ll Value, rhs: &'ll Value
+) -> &'ll Value {
     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bx, rhs);
@@ -370,17 +378,17 @@ pub fn build_unchecked_rshift<'a, 'tcx>(
     }
 }
 
-fn shift_mask_rhs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef {
+fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
     let rhs_llty = val_ty(rhs);
     bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
 }
 
-pub fn shift_mask_val<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    llty: Type,
-    mask_llty: Type,
+pub fn shift_mask_val(
+    bx: &Builder<'a, 'll, 'tcx>,
+    llty: &'ll Type,
+    mask_llty: &'ll Type,
     invert: bool
-) -> ValueRef {
+) -> &'ll Value {
     let kind = llty.kind();
     match kind {
         TypeKind::Integer => {
index f0b5f4b887971f1cffa7bc150ef450d24d7c2ab0..72ff65361cada9d3e6974d100f27f1a61f2f76fe 100644 (file)
@@ -9,9 +9,7 @@
 // except according to those terms.
 
 use libc::c_uint;
-use llvm;
-use llvm::{SetUnnamedAddr};
-use llvm::{ValueRef, True};
+use llvm::{self, SetUnnamedAddr, True};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map as hir_map;
 use debuginfo;
 use syntax_pos::symbol::LocalInternedString;
 use type_::Type;
 use type_of::LayoutLlvmExt;
+use value::Value;
 use rustc::ty::{self, Ty};
+
 use rustc::ty::layout::{Align, LayoutOf};
 
 use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags};
 
 use std::ffi::{CStr, CString};
 
-pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
+pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstPointerCast(val, ty.to_ref())
+        llvm::LLVMConstPointerCast(val, ty)
     }
 }
 
-pub fn bitcast(val: ValueRef, ty: Type) -> ValueRef {
+pub fn bitcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value {
     unsafe {
-        llvm::LLVMConstBitCast(val, ty.to_ref())
+        llvm::LLVMConstBitCast(val, ty)
     }
 }
 
-fn set_global_alignment(cx: &CodegenCx,
-                        gv: ValueRef,
+fn set_global_alignment(cx: &CodegenCx<'ll, '_>,
+                        gv: &'ll Value,
                         mut align: Align) {
     // The target may require greater alignment for globals than the type does.
     // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
@@ -62,11 +62,12 @@ fn set_global_alignment(cx: &CodegenCx,
     }
 }
 
-pub fn addr_of_mut(cx: &CodegenCx,
-                   cv: ValueRef,
-                   align: Align,
-                   kind: &str)
-                    -> ValueRef {
+pub fn addr_of_mut(
+    cx: &CodegenCx<'ll, '_>,
+    cv: &'ll Value,
+    align: Align,
+    kind: &str,
+) -> &'ll Value {
     unsafe {
         let name = cx.generate_local_symbol_name(kind);
         let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{
@@ -80,11 +81,12 @@ pub fn addr_of_mut(cx: &CodegenCx,
     }
 }
 
-pub fn addr_of(cx: &CodegenCx,
-               cv: ValueRef,
-               align: Align,
-               kind: &str)
-               -> ValueRef {
+pub fn addr_of(
+    cx: &CodegenCx<'ll, '_>,
+    cv: &'ll Value,
+    align: Align,
+    kind: &str,
+) -> &'ll Value {
     if let Some(&gv) = cx.const_globals.borrow().get(&cv) {
         unsafe {
             // Upgrade the alignment in cases where the same constant is used with different
@@ -104,7 +106,7 @@ pub fn addr_of(cx: &CodegenCx,
     gv
 }
 
-pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
+pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
     let instance = Instance::mono(cx.tcx, def_id);
     if let Some(&g) = cx.instances.borrow().get(&instance) {
         return g;
@@ -213,13 +215,13 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
     g
 }
 
-fn check_and_apply_linkage<'tcx>(
-    cx: &CodegenCx<'_, 'tcx>,
+fn check_and_apply_linkage(
+    cx: &CodegenCx<'ll, 'tcx>,
     attrs: &CodegenFnAttrs,
     ty: Ty<'tcx>,
     sym: LocalInternedString,
     span: Option<Span>
-) -> ValueRef {
+) -> &'ll Value {
     let llty = cx.layout_of(ty).llvm_type(cx);
     if let Some(linkage) = attrs.linkage {
         debug!("get_static: sym={} linkage={:?}", sym, linkage);
@@ -294,7 +296,7 @@ pub fn codegen_static<'a, 'tcx>(
         let mut val_llty = val_ty(v);
         let v = if val_llty == Type::i1(cx) {
             val_llty = Type::i8(cx);
-            llvm::LLVMConstZExt(v, val_llty.to_ref())
+            llvm::LLVMConstZExt(v, val_llty)
         } else {
             v
         };
@@ -316,7 +318,7 @@ pub fn codegen_static<'a, 'tcx>(
             let visibility = llvm::LLVMRustGetVisibility(g);
 
             let new_g = llvm::LLVMRustGetOrInsertGlobal(
-                cx.llmod, name_string.as_ptr(), val_llty.to_ref());
+                cx.llmod, name_string.as_ptr(), val_llty);
 
             llvm::LLVMRustSetLinkage(new_g, linkage);
             llvm::LLVMRustSetVisibility(new_g, visibility);
@@ -411,7 +413,7 @@ pub fn codegen_static<'a, 'tcx>(
 
         if attrs.flags.contains(CodegenFnAttrFlags::USED) {
             // This static will be stored in the llvm.used variable which is an array of i8*
-            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx));
             cx.used_statics.borrow_mut().push(cast);
         }
     }
index b774d7c5def217a9a17f5bc501bc8ef60cdb7d07..2f557d0b099986eb9d716ce5f2569b28e4819709 100644 (file)
@@ -10,7 +10,6 @@
 
 use common;
 use llvm;
-use llvm::{ContextRef, ModuleRef, ValueRef};
 use rustc::dep_graph::DepGraphSafe;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
@@ -19,6 +18,7 @@
 use base;
 use declare;
 use monomorphize::Instance;
+use value::Value;
 
 use monomorphize::partitioning::CodegenUnit;
 use type_::Type;
@@ -26,7 +26,7 @@
 
 use rustc_data_structures::base_n;
 use rustc::mir::mono::Stats;
-use rustc::session::config::{self, NoDebugInfo};
+use rustc::session::config::{self, DebugInfo};
 use rustc::session::Session;
 use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout};
 use rustc::ty::{self, Ty, TyCtxt};
@@ -35,7 +35,6 @@
 
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
-use std::ptr;
 use std::iter;
 use std::str;
 use std::sync::Arc;
 use abi::Abi;
 
 /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
-/// `ContextRef` so that several compilation units may be optimized in parallel.
-/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`.
+/// `llvm::Context` so that several compilation units may be optimized in parallel.
+/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
 pub struct CodegenCx<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub check_overflow: bool,
     pub use_dll_storage_attrs: bool,
     pub tls_model: llvm::ThreadLocalMode,
 
-    pub llmod: ModuleRef,
-    pub llcx: ContextRef,
+    pub llmod: &'a llvm::Module,
+    pub llcx: &'a llvm::Context,
     pub stats: RefCell<Stats>,
     pub codegen_unit: Arc<CodegenUnit<'tcx>>,
 
     /// Cache instances of monomorphic and polymorphic items
-    pub instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
+    pub instances: RefCell<FxHashMap<Instance<'tcx>, &'a Value>>,
     /// Cache generated vtables
     pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
-                                Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
+                                Option<ty::PolyExistentialTraitRef<'tcx>>), &'a Value>>,
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, ValueRef>>,
+    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'a Value>>,
 
     /// Reverse-direction for const ptrs cast from globals.
-    /// Key is a ValueRef holding a *T,
-    /// Val is a ValueRef holding a *[T].
+    /// Key is a Value holding a *T,
+    /// Val is a Value holding a *[T].
     ///
     /// Needed because LLVM loses pointer->pointee association
     /// when we ptrcast, and we have to ptrcast during codegen
     /// of a [T] const because we form a slice, a (*T,usize) pair, not
     /// a pointer to an LLVM array type. Similar for trait objects.
-    pub const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
+    pub const_unsized: RefCell<FxHashMap<&'a Value, &'a Value>>,
 
     /// Cache of emitted const globals (value -> global)
-    pub const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
+    pub const_globals: RefCell<FxHashMap<&'a Value, &'a Value>>,
 
     /// Mapping from static definitions to their DefId's.
-    pub statics: RefCell<FxHashMap<ValueRef, DefId>>,
+    pub statics: RefCell<FxHashMap<&'a Value, DefId>>,
 
     /// List of globals for static variables which need to be passed to the
     /// LLVM function ReplaceAllUsesWith (RAUW) when codegen is complete.
-    /// (We have to make sure we don't invalidate any ValueRefs referring
+    /// (We have to make sure we don't invalidate any Values referring
     /// to constants.)
-    pub statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
+    pub statics_to_rauw: RefCell<Vec<(&'a Value, &'a Value)>>,
 
     /// Statics that will be placed in the llvm.used variable
     /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
-    pub used_statics: RefCell<Vec<ValueRef>>,
+    pub used_statics: RefCell<Vec<&'a Value>>,
 
-    pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), Type>>,
-    pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
+    pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), &'a Type>>,
+    pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'a Type>>,
     pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
-    pub isize_ty: Type,
+    pub isize_ty: &'a Type,
 
-    pub dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
+    pub dbg_cx: Option<debuginfo::CrateDebugContext<'a, 'tcx>>,
 
-    eh_personality: Cell<Option<ValueRef>>,
-    eh_unwind_resume: Cell<Option<ValueRef>>,
-    pub rust_try_fn: Cell<Option<ValueRef>>,
+    eh_personality: Cell<Option<&'a Value>>,
+    eh_unwind_resume: Cell<Option<&'a Value>>,
+    pub rust_try_fn: Cell<Option<&'a Value>>,
 
-    intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>,
+    intrinsics: RefCell<FxHashMap<&'static str, &'a Value>>,
 
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
@@ -148,7 +147,7 @@ fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
 
 fn is_any_library(sess: &Session) -> bool {
     sess.crate_types.borrow().iter().any(|ty| {
-        *ty != config::CrateTypeExecutable
+        *ty != config::CrateType::Executable
     })
 }
 
@@ -156,8 +155,11 @@ pub fn is_pie_binary(sess: &Session) -> bool {
     !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
 }
 
-pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
-    let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
+pub unsafe fn create_module(
+    sess: &Session,
+    llcx: &'ll llvm::Context,
+    mod_name: &str,
+) -> &'ll llvm::Module {
     let mod_name = CString::new(mod_name).unwrap();
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
@@ -209,13 +211,13 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont
         llvm::LLVMRustSetModulePIELevel(llmod);
     }
 
-    (llcx, llmod)
+    llmod
 }
 
 impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                codegen_unit: Arc<CodegenUnit<'tcx>>,
-               llmod_id: &str)
+               llvm_module: &'a ::ModuleLlvm)
                -> CodegenCx<'a, 'tcx> {
         // An interesting part of Windows which MSVC forces our hand on (and
         // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
@@ -266,55 +268,48 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         let tls_model = get_tls_model(&tcx.sess);
 
-        unsafe {
-            let (llcx, llmod) = create_context_and_module(&tcx.sess,
-                                                          &llmod_id[..]);
-
-            let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
-                let dctx = debuginfo::CrateDebugContext::new(llmod);
-                debuginfo::metadata::compile_unit_metadata(tcx,
-                                                           &codegen_unit.name().as_str(),
-                                                           &dctx);
-                Some(dctx)
-            } else {
-                None
-            };
-
-            let mut cx = CodegenCx {
-                tcx,
-                check_overflow,
-                use_dll_storage_attrs,
-                tls_model,
-                llmod,
-                llcx,
-                stats: RefCell::new(Stats::default()),
-                codegen_unit,
-                instances: RefCell::new(FxHashMap()),
-                vtables: RefCell::new(FxHashMap()),
-                const_cstr_cache: RefCell::new(FxHashMap()),
-                const_unsized: RefCell::new(FxHashMap()),
-                const_globals: RefCell::new(FxHashMap()),
-                statics: RefCell::new(FxHashMap()),
-                statics_to_rauw: RefCell::new(Vec::new()),
-                used_statics: RefCell::new(Vec::new()),
-                lltypes: RefCell::new(FxHashMap()),
-                scalar_lltypes: RefCell::new(FxHashMap()),
-                pointee_infos: RefCell::new(FxHashMap()),
-                isize_ty: Type::from_ref(ptr::null_mut()),
-                dbg_cx,
-                eh_personality: Cell::new(None),
-                eh_unwind_resume: Cell::new(None),
-                rust_try_fn: Cell::new(None),
-                intrinsics: RefCell::new(FxHashMap()),
-                local_gen_sym_counter: Cell::new(0),
-            };
-            cx.isize_ty = Type::isize(&cx);
-            cx
-        }
-    }
+        let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
 
-    pub fn into_stats(self) -> Stats {
-        self.stats.into_inner()
+        let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
+            let dctx = debuginfo::CrateDebugContext::new(llmod);
+            debuginfo::metadata::compile_unit_metadata(tcx,
+                                                        &codegen_unit.name().as_str(),
+                                                        &dctx);
+            Some(dctx)
+        } else {
+            None
+        };
+
+        let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
+
+        CodegenCx {
+            tcx,
+            check_overflow,
+            use_dll_storage_attrs,
+            tls_model,
+            llmod,
+            llcx,
+            stats: RefCell::new(Stats::default()),
+            codegen_unit,
+            instances: RefCell::new(FxHashMap()),
+            vtables: RefCell::new(FxHashMap()),
+            const_cstr_cache: RefCell::new(FxHashMap()),
+            const_unsized: RefCell::new(FxHashMap()),
+            const_globals: RefCell::new(FxHashMap()),
+            statics: RefCell::new(FxHashMap()),
+            statics_to_rauw: RefCell::new(Vec::new()),
+            used_statics: RefCell::new(Vec::new()),
+            lltypes: RefCell::new(FxHashMap()),
+            scalar_lltypes: RefCell::new(FxHashMap()),
+            pointee_infos: RefCell::new(FxHashMap()),
+            isize_ty,
+            dbg_cx,
+            eh_personality: Cell::new(None),
+            eh_unwind_resume: Cell::new(None),
+            rust_try_fn: Cell::new(None),
+            intrinsics: RefCell::new(FxHashMap()),
+            local_gen_sym_counter: Cell::new(0),
+        }
     }
 }
 
@@ -323,7 +318,7 @@ pub fn sess<'a>(&'a self) -> &'a Session {
         &self.tcx.sess
     }
 
-    pub fn get_intrinsic(&self, key: &str) -> ValueRef {
+    pub fn get_intrinsic(&self, key: &str) -> &'b Value {
         if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
             return v;
         }
@@ -347,7 +342,7 @@ pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
         name
     }
 
-    pub fn eh_personality(&self) -> ValueRef {
+    pub fn eh_personality(&self) -> &'b Value {
         // The exception handling personality function.
         //
         // If our compilation unit has the `eh_personality` lang item somewhere
@@ -382,7 +377,7 @@ pub fn eh_personality(&self) -> ValueRef {
                 } else {
                     "rust_eh_personality"
                 };
-                let fty = Type::variadic_func(&[], &Type::i32(self));
+                let fty = Type::variadic_func(&[], Type::i32(self));
                 declare::declare_cfn(self, name, fty)
             }
         };
@@ -390,9 +385,9 @@ pub fn eh_personality(&self) -> ValueRef {
         llfn
     }
 
-    // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
+    // Returns a Value of the "eh_unwind_resume" lang item if one is defined,
     // otherwise declares it as an external function.
-    pub fn eh_unwind_resume(&self) -> ValueRef {
+    pub fn eh_unwind_resume(&self) -> &'b Value {
         use attributes;
         let unwresume = &self.eh_unwind_resume;
         if let Some(llfn) = unwresume.get() {
@@ -448,25 +443,25 @@ pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
     }
 }
 
-impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CodegenCx<'a, 'tcx> {
+impl ty::layout::HasDataLayout for &'a CodegenCx<'ll, 'tcx> {
     fn data_layout(&self) -> &ty::layout::TargetDataLayout {
         &self.tcx.data_layout
     }
 }
 
-impl<'a, 'tcx> HasTargetSpec for &'a CodegenCx<'a, 'tcx> {
+impl HasTargetSpec for &'a CodegenCx<'ll, 'tcx> {
     fn target_spec(&self) -> &Target {
         &self.tcx.sess.target.target
     }
 }
 
-impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'a, 'tcx> {
+impl ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'ll, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.tcx
     }
 }
 
-impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> {
+impl LayoutOf for &'a CodegenCx<'ll, 'tcx> {
     type Ty = Ty<'tcx>;
     type TyLayout = TyLayout<'tcx>;
 
@@ -480,11 +475,11 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
 }
 
 /// Declare any llvm intrinsics that you might need
-fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
+fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> {
     macro_rules! ifn {
         ($name:expr, fn() -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(cx, $name, Type::func(&[], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::func(&[], $ret));
                 llvm::SetUnnamedAddr(f, false);
                 cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
@@ -492,7 +487,7 @@ macro_rules! ifn {
         );
         ($name:expr, fn(...) -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], $ret));
                 llvm::SetUnnamedAddr(f, false);
                 cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
@@ -500,7 +495,7 @@ macro_rules! ifn {
         );
         ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
             if key == $name {
-                let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], &$ret));
+                let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], $ret));
                 llvm::SetUnnamedAddr(f, false);
                 cx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
@@ -522,14 +517,14 @@ macro_rules! mk_struct {
     let t_f32 = Type::f32(cx);
     let t_f64 = Type::f64(cx);
 
-    let t_v2f32 = Type::vector(&t_f32, 2);
-    let t_v4f32 = Type::vector(&t_f32, 4);
-    let t_v8f32 = Type::vector(&t_f32, 8);
-    let t_v16f32 = Type::vector(&t_f32, 16);
+    let t_v2f32 = Type::vector(t_f32, 2);
+    let t_v4f32 = Type::vector(t_f32, 4);
+    let t_v8f32 = Type::vector(t_f32, 8);
+    let t_v16f32 = Type::vector(t_f32, 16);
 
-    let t_v2f64 = Type::vector(&t_f64, 2);
-    let t_v4f64 = Type::vector(&t_f64, 4);
-    let t_v8f64 = Type::vector(&t_f64, 8);
+    let t_v2f64 = Type::vector(t_f64, 2);
+    let t_v4f64 = Type::vector(t_f64, 4);
+    let t_v8f64 = Type::vector(t_f64, 8);
 
     ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
     ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
@@ -775,7 +770,7 @@ macro_rules! mk_struct {
     ifn!("llvm.assume", fn(i1) -> void);
     ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
 
-    if cx.sess().opts.debuginfo != NoDebugInfo {
+    if cx.sess().opts.debuginfo != DebugInfo::None {
         ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void);
         ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void);
     }
index fcde7f9bbc33d8c1cc3681aaf049f5256d4b373d..a76f1d50fa7bf89551717ec1eb9164b44837c1f8 100644 (file)
 use rustc::mir::{Mir, SourceScope};
 
 use libc::c_uint;
-use std::ptr;
 
 use syntax_pos::Pos;
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use syntax_pos::BytePos;
 
 #[derive(Clone, Copy, Debug)]
-pub struct MirDebugScope {
-    pub scope_metadata: DIScope,
+pub struct MirDebugScope<'ll> {
+    pub scope_metadata: Option<&'ll DIScope>,
     // Start and end offsets of the file to which this DIScope belongs.
     // These are used to quickly determine whether some span refers to the same file.
     pub file_start_pos: BytePos,
     pub file_end_pos: BytePos,
 }
 
-impl MirDebugScope {
+impl MirDebugScope<'ll> {
     pub fn is_valid(&self) -> bool {
-        !self.scope_metadata.is_null()
+        !self.scope_metadata.is_none()
     }
 }
 
 /// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
 /// If debuginfo is disabled, the returned vector is empty.
-pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebugContext)
-    -> IndexVec<SourceScope, MirDebugScope> {
+pub fn create_mir_scopes(
+    cx: &CodegenCx<'ll, '_>,
+    mir: &Mir,
+    debug_context: &FunctionDebugContext<'ll>,
+) -> IndexVec<SourceScope, MirDebugScope<'ll>> {
     let null_scope = MirDebugScope {
-        scope_metadata: ptr::null_mut(),
+        scope_metadata: None,
         file_start_pos: BytePos(0),
         file_end_pos: BytePos(0)
     };
@@ -62,7 +64,7 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu
     };
 
     // Find all the scopes with variables defined in them.
-    let mut has_variables = BitVector::new(mir.source_scopes.len());
+    let mut has_variables = BitArray::new(mir.source_scopes.len());
     for var in mir.vars_iter() {
         let decl = &mir.local_decls[var];
         has_variables.insert(decl.visibility_scope);
@@ -77,12 +79,12 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu
     scopes
 }
 
-fn make_mir_scope(cx: &CodegenCx,
+fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
                   mir: &Mir,
-                  has_variables: &BitVector<SourceScope>,
-                  debug_context: &FunctionDebugContextData,
+                  has_variables: &BitArray<SourceScope>,
+                  debug_context: &FunctionDebugContextData<'ll>,
                   scope: SourceScope,
-                  scopes: &mut IndexVec<SourceScope, MirDebugScope>) {
+                  scopes: &mut IndexVec<SourceScope, MirDebugScope<'ll>>) {
     if scopes[scope].is_valid() {
         return;
     }
@@ -95,7 +97,7 @@ fn make_mir_scope(cx: &CodegenCx,
         // The root is the function itself.
         let loc = span_start(cx, mir.span);
         scopes[scope] = MirDebugScope {
-            scope_metadata: debug_context.fn_metadata,
+            scope_metadata: Some(debug_context.fn_metadata),
             file_start_pos: loc.file.start_pos,
             file_end_pos: loc.file.end_pos,
         };
@@ -109,7 +111,7 @@ fn make_mir_scope(cx: &CodegenCx,
         // However, we don't skip creating a nested scope if
         // our parent is the root, because we might want to
         // put arguments in the root and not have shadowing.
-        if parent_scope.scope_metadata != debug_context.fn_metadata {
+        if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata {
             scopes[scope] = parent_scope;
             return;
         }
@@ -121,12 +123,12 @@ fn make_mir_scope(cx: &CodegenCx,
                                       debug_context.defining_crate);
 
     let scope_metadata = unsafe {
-        llvm::LLVMRustDIBuilderCreateLexicalBlock(
+        Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
             DIB(cx),
-            parent_scope.scope_metadata,
+            parent_scope.scope_metadata.unwrap(),
             file_metadata,
             loc.line as c_uint,
-            loc.col.to_usize() as c_uint)
+            loc.col.to_usize() as c_uint))
     };
     scopes[scope] = MirDebugScope {
         scope_metadata,
index 0b4858c7ab051085350c48fa95fa01d0e05fd5c3..f6faddb894ffdf41c532659fffc92afea806f412 100644 (file)
 use common::{C_bytes, CodegenCx, C_i32};
 use builder::Builder;
 use declare;
+use rustc::session::config::DebugInfo;
 use type_::Type;
-use rustc::session::config::NoDebugInfo;
+use value::Value;
 
-use std::ptr;
 use syntax::attr;
 
 
@@ -40,8 +40,8 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &Builder) {
 
 /// Allocates the global variable responsible for the .debug_gdb_scripts binary
 /// section.
-pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
-                                                  -> llvm::ValueRef {
+pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
+                                                  -> &'ll Value {
     let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0";
     let section_var_name = &c_section_var_name[..c_section_var_name.len()-1];
 
@@ -50,12 +50,12 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
                                  c_section_var_name.as_ptr() as *const _)
     };
 
-    if section_var == ptr::null_mut() {
+    section_var.unwrap_or_else(|| {
         let section_name = b".debug_gdb_scripts\0";
         let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
 
         unsafe {
-            let llvm_type = Type::array(&Type::i8(cx),
+            let llvm_type = Type::array(Type::i8(cx),
                                         section_contents.len() as u64);
 
             let section_var = declare::define_global(cx, section_var_name,
@@ -72,9 +72,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx)
             llvm::LLVMSetAlignment(section_var, 1);
             section_var
         }
-    } else {
-        section_var
-    }
+    })
 }
 
 pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool {
@@ -83,6 +81,6 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool {
                             "omit_gdb_pretty_printer_section");
 
     !omit_gdb_pretty_printer_section &&
-    cx.sess().opts.debuginfo != NoDebugInfo &&
+    cx.sess().opts.debuginfo != DebugInfo::None &&
     cx.sess().target.target.options.emit_debug_gdb_scripts
 }
index 2f4dd5a7ce5bb0c3887fd46671943db43a995c05..69ef92ed98e52d51112f59381e14efc8828a3393 100644 (file)
@@ -18,8 +18,9 @@
 use super::type_names::compute_debuginfo_type_name;
 use super::{CrateDebugContext};
 use abi;
+use value::Value;
 
-use llvm::{self, ValueRef};
+use llvm;
 use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
                       DICompositeType, DILexicalBlock, DIFlags};
 
@@ -38,7 +39,8 @@
 
 use libc::{c_uint, c_longlong};
 use std::ffi::CString;
-use std::fmt::Write;
+use std::fmt::{self, Write};
+use std::hash::{Hash, Hasher};
 use std::iter;
 use std::ptr;
 use std::path::{Path, PathBuf};
 use syntax::symbol::{Interner, InternedString, Symbol};
 use syntax_pos::{self, Span, FileName};
 
+impl PartialEq for llvm::Metadata {
+    fn eq(&self, other: &Self) -> bool {
+        self as *const _ == other as *const _
+    }
+}
+
+impl Eq for llvm::Metadata {}
+
+impl Hash for llvm::Metadata {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        (self as *const Self).hash(hasher);
+    }
+}
+
+impl fmt::Debug for llvm::Metadata {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        (self as *const Self).fmt(f)
+    }
+}
 
 // From DWARF 5.
 // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
@@ -64,8 +85,7 @@
 pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
 pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
 
-// ptr::null() doesn't work :(
-pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
+pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
 
 #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
 pub struct UniqueTypeId(ast::Name);
 // created so far. The metadata nodes are indexed by UniqueTypeId, and, for
 // faster lookup, also by Ty. The TypeMap is responsible for creating
 // UniqueTypeIds.
-pub struct TypeMap<'tcx> {
+pub struct TypeMap<'ll, 'tcx> {
     // The UniqueTypeIds created so far
     unique_id_interner: Interner,
     // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
-    unique_id_to_metadata: FxHashMap<UniqueTypeId, DIType>,
+    unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
     // A map from types to debuginfo metadata. This is a N:1 mapping.
-    type_to_metadata: FxHashMap<Ty<'tcx>, DIType>,
+    type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
     // A map from types to UniqueTypeId. This is a N:1 mapping.
     type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>
 }
 
-impl<'tcx> TypeMap<'tcx> {
-    pub fn new() -> TypeMap<'tcx> {
+impl TypeMap<'ll, 'tcx> {
+    pub fn new() -> Self {
         TypeMap {
             unique_id_interner: Interner::new(),
             type_to_metadata: FxHashMap(),
@@ -97,9 +117,11 @@ pub fn new() -> TypeMap<'tcx> {
 
     // Adds a Ty to metadata mapping to the TypeMap. The method will fail if
     // the mapping already exists.
-    fn register_type_with_metadata<'a>(&mut self,
-                                       type_: Ty<'tcx>,
-                                       metadata: DIType) {
+    fn register_type_with_metadata(
+        &mut self,
+        type_: Ty<'tcx>,
+        metadata: &'ll DIType,
+    ) {
         if self.type_to_metadata.insert(type_, metadata).is_some() {
             bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_);
         }
@@ -107,20 +129,22 @@ fn register_type_with_metadata<'a>(&mut self,
 
     // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
     // fail if the mapping already exists.
-    fn register_unique_id_with_metadata(&mut self,
-                                        unique_type_id: UniqueTypeId,
-                                        metadata: DIType) {
+    fn register_unique_id_with_metadata(
+        &mut self,
+        unique_type_id: UniqueTypeId,
+        metadata: &'ll DIType,
+    ) {
         if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
             bug!("Type metadata for unique id '{}' is already in the TypeMap!",
                  self.get_unique_type_id_as_string(unique_type_id));
         }
     }
 
-    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<DIType> {
+    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> {
         self.type_to_metadata.get(&type_).cloned()
     }
 
-    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DIType> {
+    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> {
         self.unique_id_to_metadata.get(&unique_type_id).cloned()
     }
 
@@ -182,23 +206,23 @@ fn get_unique_type_id_of_enum_variant<'a>(&mut self,
 // needed to generate the missing parts of the description. See the
 // documentation section on Recursive Types at the top of this file for more
 // information.
-enum RecursiveTypeDescription<'tcx> {
+enum RecursiveTypeDescription<'ll, 'tcx> {
     UnfinishedMetadata {
         unfinished_type: Ty<'tcx>,
         unique_type_id: UniqueTypeId,
-        metadata_stub: DICompositeType,
-        member_description_factory: MemberDescriptionFactory<'tcx>,
+        metadata_stub: &'ll DICompositeType,
+        member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
     },
-    FinalMetadata(DICompositeType)
+    FinalMetadata(&'ll DICompositeType)
 }
 
-fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
-    cx: &CodegenCx<'a, 'tcx>,
+fn create_and_register_recursive_type_forward_declaration(
+    cx: &CodegenCx<'ll, 'tcx>,
     unfinished_type: Ty<'tcx>,
     unique_type_id: UniqueTypeId,
-    metadata_stub: DICompositeType,
-    member_description_factory: MemberDescriptionFactory<'tcx>)
- -> RecursiveTypeDescription<'tcx> {
+    metadata_stub: &'ll DICompositeType,
+    member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
 
     // Insert the stub into the TypeMap in order to allow for recursive references
     let mut type_map = debug_context(cx).type_map.borrow_mut();
@@ -213,11 +237,11 @@ fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
     }
 }
 
-impl<'tcx> RecursiveTypeDescription<'tcx> {
+impl RecursiveTypeDescription<'ll, 'tcx> {
     // Finishes up the description of the type in question (mostly by providing
     // descriptions of the fields of the given type) and returns the final type
     // metadata.
-    fn finalize<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> MetadataCreationResult {
+    fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
         match *self {
             FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
             UnfinishedMetadata {
@@ -269,12 +293,13 @@ macro_rules! return_if_metadata_created_in_meantime {
     )
 }
 
-fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                unique_type_id: UniqueTypeId,
-                                array_or_slice_type: Ty<'tcx>,
-                                element_type: Ty<'tcx>,
-                                span: Span)
-                                -> MetadataCreationResult {
+fn fixed_vec_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    unique_type_id: UniqueTypeId,
+    array_or_slice_type: Ty<'tcx>,
+    element_type: Ty<'tcx>,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
     let element_type_metadata = type_metadata(cx, element_type, span);
 
     return_if_metadata_created_in_meantime!(cx, unique_type_id);
@@ -289,7 +314,7 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     };
 
     let subrange = unsafe {
-        llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
+        Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound))
     };
 
     let subscripts = create_DIArray(DIB(cx), &[subrange]);
@@ -305,12 +330,13 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     return MetadataCreationResult::new(metadata, false);
 }
 
-fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                slice_ptr_type: Ty<'tcx>,
-                                element_type: Ty<'tcx>,
-                                unique_type_id: UniqueTypeId,
-                                span: Span)
-                                -> MetadataCreationResult {
+fn vec_slice_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    slice_ptr_type: Ty<'tcx>,
+    element_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
     let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
 
     let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
@@ -354,26 +380,28 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     MetadataCreationResult::new(metadata, false)
 }
 
-fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                      unique_type_id: UniqueTypeId,
-                                      signature: ty::PolyFnSig<'tcx>,
-                                      span: Span)
-                                      -> MetadataCreationResult
-{
+fn subroutine_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    unique_type_id: UniqueTypeId,
+    signature: ty::PolyFnSig<'tcx>,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
     let signature = cx.tcx.normalize_erasing_late_bound_regions(
         ty::ParamEnv::reveal_all(),
         &signature,
     );
 
-    let signature_metadata: Vec<DIType> = iter::once(
+    let signature_metadata: Vec<_> = iter::once(
         // return type
         match signature.output().sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
-            _ => type_metadata(cx, signature.output(), span)
+            ty::TyTuple(ref tys) if tys.is_empty() => None,
+            _ => Some(type_metadata(cx, signature.output(), span))
         }
     ).chain(
         // regular arguments
-        signature.inputs().iter().map(|argument_type| type_metadata(cx, argument_type, span))
+        signature.inputs().iter().map(|argument_type| {
+            Some(type_metadata(cx, argument_type, span))
+        })
     ).collect();
 
     return_if_metadata_created_in_meantime!(cx, unique_type_id);
@@ -394,11 +422,12 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 // trait_type should be the actual trait (e.g., Trait). Where the trait is part
 // of a DST struct, there is no trait_object_type and the results of this
 // function will be a little bit weird.
-fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    trait_type: Ty<'tcx>,
-                                    trait_object_type: Option<Ty<'tcx>>,
-                                    unique_type_id: UniqueTypeId)
-                                    -> DIType {
+fn trait_pointer_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    trait_type: Ty<'tcx>,
+    trait_object_type: Option<Ty<'tcx>>,
+    unique_type_id: UniqueTypeId,
+) -> &'ll DIType {
     // The implementation provided here is a stub. It makes sure that the trait
     // type is assigned the correct name, size, namespace, and source location.
     // But it does not describe the trait's methods.
@@ -406,7 +435,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     let containing_scope = match trait_type.sty {
         ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() {
             let def_id = principal.def_id();
-            get_namespace_for_item(cx, def_id)
+            Some(get_namespace_for_item(cx, def_id))
         } else {
             NO_SCOPE_METADATA
         },
@@ -461,10 +490,11 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                             syntax_pos::DUMMY_SP)
 }
 
-pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                               t: Ty<'tcx>,
-                               usage_site_span: Span)
-                               -> DIType {
+pub fn type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    t: Ty<'tcx>,
+    usage_site_span: Span,
+) -> &'ll DIType {
     // Get the unique type id of this type.
     let unique_type_id = {
         let mut type_map = debug_context(cx).type_map.borrow_mut();
@@ -681,9 +711,9 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     metadata
 }
 
-pub fn file_metadata(cx: &CodegenCx,
+pub fn file_metadata(cx: &CodegenCx<'ll, '_>,
                      file_name: &FileName,
-                     defining_crate: CrateNum) -> DIFile {
+                     defining_crate: CrateNum) -> &'ll DIFile {
     debug!("file_metadata: file_name: {}, defining_crate: {}",
            file_name,
            defining_crate);
@@ -699,14 +729,14 @@ pub fn file_metadata(cx: &CodegenCx,
     file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy())
 }
 
-pub fn unknown_file_metadata(cx: &CodegenCx) -> DIFile {
+pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
     file_metadata_raw(cx, "<unknown>", "")
 }
 
-fn file_metadata_raw(cx: &CodegenCx,
+fn file_metadata_raw(cx: &CodegenCx<'ll, '_>,
                      file_name: &str,
                      directory: &str)
-                     -> DIFile {
+                     -> &'ll DIFile {
     let key = (Symbol::intern(file_name), Symbol::intern(directory));
 
     if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) {
@@ -729,9 +759,7 @@ fn file_metadata_raw(cx: &CodegenCx,
     file_metadata
 }
 
-fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                 t: Ty<'tcx>) -> DIType {
-
+fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
     debug!("basic_type_metadata: {:?}", t);
 
     let (name, encoding) = match t.sty {
@@ -766,19 +794,22 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     return ty_metadata;
 }
 
-fn foreign_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   t: Ty<'tcx>,
-                                   unique_type_id: UniqueTypeId) -> DIType {
+fn foreign_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    t: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+) -> &'ll DIType {
     debug!("foreign_type_metadata: {:?}", t);
 
     let name = compute_debuginfo_type_name(cx, t, false);
     create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA)
 }
 
-fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   pointer_type: Ty<'tcx>,
-                                   pointee_type_metadata: DIType)
-                                   -> DIType {
+fn pointer_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    pointer_type: Ty<'tcx>,
+    pointee_type_metadata: &'ll DIType,
+) -> &'ll DIType {
     let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
     let name = compute_debuginfo_type_name(cx, pointer_type, false);
     let name = CString::new(name).unwrap();
@@ -794,8 +825,8 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
 pub fn compile_unit_metadata(tcx: TyCtxt,
                              codegen_unit_name: &str,
-                             debug_context: &CrateDebugContext)
-                             -> DIDescriptor {
+                             debug_context: &CrateDebugContext<'ll, '_>)
+                             -> &'ll DIDescriptor {
     let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
         Some(ref path) => path.clone(),
         None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
@@ -860,7 +891,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt,
         return unit_metadata;
     };
 
-    fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef {
+    fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
         let path_str = path2cstr(path);
         unsafe {
             llvm::LLVMMDStringInContext(llcx,
@@ -870,13 +901,13 @@ fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef {
     }
 }
 
-struct MetadataCreationResult {
-    metadata: DIType,
+struct MetadataCreationResult<'ll> {
+    metadata: &'ll DIType,
     already_stored_in_typemap: bool
 }
 
-impl MetadataCreationResult {
-    fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult {
+impl MetadataCreationResult<'ll> {
+    fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
         MetadataCreationResult {
             metadata,
             already_stored_in_typemap,
@@ -887,9 +918,9 @@ fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationRes
 // Description of a type member, which can either be a regular field (as in
 // structs or tuples) or an enum variant.
 #[derive(Debug)]
-struct MemberDescription {
+struct MemberDescription<'ll> {
     name: String,
-    type_metadata: DIType,
+    type_metadata: &'ll DIType,
     offset: Size,
     size: Size,
     align: Align,
@@ -900,17 +931,17 @@ struct MemberDescription {
 // for some record-like type. MemberDescriptionFactories are used to defer the
 // creation of type member descriptions in order to break cycles arising from
 // recursive type definitions.
-enum MemberDescriptionFactory<'tcx> {
+enum MemberDescriptionFactory<'ll, 'tcx> {
     StructMDF(StructMemberDescriptionFactory<'tcx>),
     TupleMDF(TupleMemberDescriptionFactory<'tcx>),
-    EnumMDF(EnumMemberDescriptionFactory<'tcx>),
+    EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
     UnionMDF(UnionMemberDescriptionFactory<'tcx>),
-    VariantMDF(VariantMemberDescriptionFactory<'tcx>)
+    VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>)
 }
 
-impl<'tcx> MemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+impl MemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         match *self {
             StructMDF(ref this) => {
                 this.create_member_descriptions(cx)
@@ -943,8 +974,8 @@ struct StructMemberDescriptionFactory<'tcx> {
 }
 
 impl<'tcx> StructMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         let layout = cx.layout_of(self.ty);
         self.variant.fields.iter().enumerate().map(|(i, f)| {
             let name = if self.variant.ctor_kind == CtorKind::Fn {
@@ -967,11 +998,12 @@ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
 }
 
 
-fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                     struct_type: Ty<'tcx>,
-                                     unique_type_id: UniqueTypeId,
-                                     span: Span)
-                                     -> RecursiveTypeDescription<'tcx> {
+fn prepare_struct_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    struct_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
 
     let (struct_def_id, variant) = match struct_type.sty {
@@ -985,7 +1017,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                                   struct_type,
                                                   &struct_name,
                                                   unique_type_id,
-                                                  containing_scope);
+                                                  Some(containing_scope));
 
     create_and_register_recursive_type_forward_declaration(
         cx,
@@ -1012,8 +1044,8 @@ struct TupleMemberDescriptionFactory<'tcx> {
 }
 
 impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         let layout = cx.layout_of(self.ty);
         self.component_types.iter().enumerate().map(|(i, &component_type)| {
             let (size, align) = cx.size_and_align_of(component_type);
@@ -1029,12 +1061,13 @@ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
     }
 }
 
-fn prepare_tuple_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    tuple_type: Ty<'tcx>,
-                                    component_types: &[Ty<'tcx>],
-                                    unique_type_id: UniqueTypeId,
-                                    span: Span)
-                                    -> RecursiveTypeDescription<'tcx> {
+fn prepare_tuple_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    tuple_type: Ty<'tcx>,
+    component_types: &[Ty<'tcx>],
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
 
     create_and_register_recursive_type_forward_declaration(
@@ -1065,8 +1098,8 @@ struct UnionMemberDescriptionFactory<'tcx> {
 }
 
 impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         self.variant.fields.iter().enumerate().map(|(i, f)| {
             let field = self.layout.field(cx, i);
             let (size, align) = field.size_and_align();
@@ -1082,11 +1115,12 @@ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
     }
 }
 
-fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    union_type: Ty<'tcx>,
-                                    unique_type_id: UniqueTypeId,
-                                    span: Span)
-                                    -> RecursiveTypeDescription<'tcx> {
+fn prepare_union_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    union_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let union_name = compute_debuginfo_type_name(cx, union_type, false);
 
     let (union_def_id, variant) = match union_type.sty {
@@ -1124,17 +1158,17 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 // the members of this union; so for every variant of the given enum, this
 // factory will produce one MemberDescription (all with no name and a fixed
 // offset of zero bytes).
-struct EnumMemberDescriptionFactory<'tcx> {
+struct EnumMemberDescriptionFactory<'ll, 'tcx> {
     enum_type: Ty<'tcx>,
     layout: TyLayout<'tcx>,
-    discriminant_type_metadata: Option<DIType>,
-    containing_scope: DIScope,
+    discriminant_type_metadata: Option<&'ll DIType>,
+    containing_scope: &'ll DIScope,
     span: Span,
 }
 
-impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+impl EnumMemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         let adt = &self.enum_type.ty_adt_def().unwrap();
         match self.layout.variants {
             layout::Variants::Single { .. } if adt.variants.is_empty() => vec![],
@@ -1259,17 +1293,17 @@ fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 }
 
 // Creates MemberDescriptions for the fields of a single enum variant.
-struct VariantMemberDescriptionFactory<'tcx> {
+struct VariantMemberDescriptionFactory<'ll, 'tcx> {
     // Cloned from the layout::Struct describing the variant.
     offsets: Vec<layout::Size>,
     args: Vec<(String, Ty<'tcx>)>,
-    discriminant_type_metadata: Option<DIType>,
+    discriminant_type_metadata: Option<&'ll DIType>,
     span: Span,
 }
 
-impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
+impl VariantMemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
+                                      -> Vec<MemberDescription<'ll>> {
         self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
             let (size, align) = cx.size_and_align_of(ty);
             MemberDescription {
@@ -1288,8 +1322,8 @@ fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>)
 }
 
 #[derive(Copy, Clone)]
-enum EnumDiscriminantInfo {
-    RegularDiscriminant(DIType),
+enum EnumDiscriminantInfo<'ll> {
+    RegularDiscriminant(&'ll DIType),
     OptimizedDiscriminant,
     NoDiscriminant
 }
@@ -1298,13 +1332,14 @@ enum EnumDiscriminantInfo {
 // of the variant, and (3) a MemberDescriptionFactory for producing the
 // descriptions of the fields of the variant. This is a rudimentary version of a
 // full RecursiveTypeDescription.
-fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   layout: layout::TyLayout<'tcx>,
-                                   variant: &'tcx ty::VariantDef,
-                                   discriminant_info: EnumDiscriminantInfo,
-                                   containing_scope: DIScope,
-                                   span: Span)
-                                   -> (DICompositeType, MemberDescriptionFactory<'tcx>) {
+fn describe_enum_variant(
+    cx: &CodegenCx<'ll, 'tcx>,
+    layout: layout::TyLayout<'tcx>,
+    variant: &'tcx ty::VariantDef,
+    discriminant_info: EnumDiscriminantInfo<'ll>,
+    containing_scope: &'ll DIScope,
+    span: Span,
+) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
     let variant_name = variant.name.as_str();
     let unique_type_id = debug_context(cx).type_map
                                           .borrow_mut()
@@ -1317,7 +1352,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                            layout.ty,
                                            &variant_name,
                                            unique_type_id,
-                                           containing_scope);
+                                           Some(containing_scope));
 
     // If this is not a univariant enum, there is also the discriminant field.
     let (discr_offset, discr_arg) = match discriminant_info {
@@ -1358,12 +1393,13 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     (metadata_stub, member_description_factory)
 }
 
-fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                   enum_type: Ty<'tcx>,
-                                   enum_def_id: DefId,
-                                   unique_type_id: UniqueTypeId,
-                                   span: Span)
-                                   -> RecursiveTypeDescription<'tcx> {
+fn prepare_enum_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    enum_type: Ty<'tcx>,
+    enum_def_id: DefId,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
     let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
 
     let containing_scope = get_namespace_for_item(cx, enum_def_id);
@@ -1376,17 +1412,17 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     let file_metadata = unknown_file_metadata(cx);
 
     let def = enum_type.ty_adt_def().unwrap();
-    let enumerators_metadata: Vec<DIDescriptor> = def.discriminants(cx.tcx)
+    let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
         .zip(&def.variants)
         .map(|(discr, v)| {
             let token = v.name.as_str();
             let name = CString::new(token.as_bytes()).unwrap();
             unsafe {
-                llvm::LLVMRustDIBuilderCreateEnumerator(
+                Some(llvm::LLVMRustDIBuilderCreateEnumerator(
                     DIB(cx),
                     name.as_ptr(),
                     // FIXME: what if enumeration has i128 discriminant?
-                    discr.val as u64)
+                    discr.val as u64))
             }
         })
         .collect();
@@ -1459,7 +1495,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         enum_type_size.bits(),
         enum_type_align.abi_bits() as u32,
         DIFlags::FlagZero,
-        ptr::null_mut(),
+        None,
         0, // RuntimeLang
         unique_type_id_str.as_ptr())
     };
@@ -1489,18 +1525,19 @@ fn get_enum_discriminant_name(cx: &CodegenCx,
 /// results in a LLVM struct.
 ///
 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
-fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                     composite_type: Ty<'tcx>,
-                                     composite_type_name: &str,
-                                     composite_type_unique_id: UniqueTypeId,
-                                     member_descriptions: &[MemberDescription],
-                                     containing_scope: DIScope,
-
-                                     // Ignore source location information as long as it
-                                     // can't be reconstructed for non-local crates.
-                                     _file_metadata: DIFile,
-                                     _definition_span: Span)
-                                     -> DICompositeType {
+fn composite_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    composite_type: Ty<'tcx>,
+    composite_type_name: &str,
+    composite_type_unique_id: UniqueTypeId,
+    member_descriptions: &[MemberDescription<'ll>],
+    containing_scope: Option<&'ll DIScope>,
+
+    // Ignore source location information as long as it
+    // can't be reconstructed for non-local crates.
+    _file_metadata: &'ll DIFile,
+    _definition_span: Span,
+) -> &'ll DICompositeType {
     // Create the (empty) struct metadata node ...
     let composite_type_metadata = create_struct_stub(cx,
                                                      composite_type,
@@ -1515,9 +1552,9 @@ fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     return composite_type_metadata;
 }
 
-fn set_members_of_composite_type(cx: &CodegenCx,
-                                 composite_type_metadata: DICompositeType,
-                                 member_descriptions: &[MemberDescription]) {
+fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>,
+                                 composite_type_metadata: &'ll DICompositeType,
+                                 member_descriptions: &[MemberDescription<'ll>]) {
     // In some rare cases LLVM metadata uniquing would lead to an existing type
     // description being used instead of a new one created in
     // create_struct_stub. This would cause a hard to trace assertion in
@@ -1535,13 +1572,13 @@ fn set_members_of_composite_type(cx: &CodegenCx,
         }
     }
 
-    let member_metadata: Vec<DIDescriptor> = member_descriptions
+    let member_metadata: Vec<_> = member_descriptions
         .iter()
         .map(|member_description| {
             let member_name = member_description.name.as_bytes();
             let member_name = CString::new(member_name).unwrap();
             unsafe {
-                llvm::LLVMRustDIBuilderCreateMemberType(
+                Some(llvm::LLVMRustDIBuilderCreateMemberType(
                     DIB(cx),
                     composite_type_metadata,
                     member_name.as_ptr(),
@@ -1551,7 +1588,7 @@ fn set_members_of_composite_type(cx: &CodegenCx,
                     member_description.align.abi_bits() as u32,
                     member_description.offset.bits(),
                     member_description.flags,
-                    member_description.type_metadata)
+                    member_description.type_metadata))
             }
         })
         .collect();
@@ -1566,12 +1603,13 @@ fn set_members_of_composite_type(cx: &CodegenCx,
 // A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do
 // any caching, does not add any fields to the struct. This can be done later
 // with set_members_of_composite_type().
-fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                struct_type: Ty<'tcx>,
-                                struct_type_name: &str,
-                                unique_type_id: UniqueTypeId,
-                                containing_scope: DIScope)
-                                -> DICompositeType {
+fn create_struct_stub(
+    cx: &CodegenCx<'ll, 'tcx>,
+    struct_type: Ty<'tcx>,
+    struct_type_name: &str,
+    unique_type_id: UniqueTypeId,
+    containing_scope: Option<&'ll DIScope>,
+) -> &'ll DICompositeType {
     let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
 
     let name = CString::new(struct_type_name).unwrap();
@@ -1593,22 +1631,23 @@ fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             struct_size.bits(),
             struct_align.abi_bits() as u32,
             DIFlags::FlagZero,
-            ptr::null_mut(),
+            None,
             empty_array,
             0,
-            ptr::null_mut(),
+            None,
             unique_type_id.as_ptr())
     };
 
     return metadata_stub;
 }
 
-fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                               union_type: Ty<'tcx>,
-                               union_type_name: &str,
-                               unique_type_id: UniqueTypeId,
-                               containing_scope: DIScope)
-                               -> DICompositeType {
+fn create_union_stub(
+    cx: &CodegenCx<'ll, 'tcx>,
+    union_type: Ty<'tcx>,
+    union_type_name: &str,
+    unique_type_id: UniqueTypeId,
+    containing_scope: &'ll DIScope,
+) -> &'ll DICompositeType {
     let (union_size, union_align) = cx.size_and_align_of(union_type);
 
     let name = CString::new(union_type_name).unwrap();
@@ -1630,7 +1669,7 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             union_size.bits(),
             union_align.abi_bits() as u32,
             DIFlags::FlagZero,
-            empty_array,
+            Some(empty_array),
             0, // RuntimeLang
             unique_type_id.as_ptr())
     };
@@ -1641,9 +1680,11 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 /// Creates debug information for the given global variable.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_global_var_metadata(cx: &CodegenCx,
-                                  def_id: DefId,
-                                  global: ValueRef) {
+pub fn create_global_var_metadata(
+    cx: &CodegenCx<'ll, '_>,
+    def_id: DefId,
+    global: &'ll Value,
+) {
     if cx.dbg_cx.is_none() {
         return;
     }
@@ -1684,7 +1725,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
 
     unsafe {
         llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
-                                                    var_scope,
+                                                    Some(var_scope),
                                                     var_name.as_ptr(),
                                                     // If null, linkage_name field is omitted,
                                                     // which is what we want for no_mangle statics
@@ -1695,18 +1736,19 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
                                                     type_metadata,
                                                     is_local_to_unit,
                                                     global,
-                                                    ptr::null_mut(),
+                                                    None,
                                                     global_align.abi() as u32,
         );
     }
 }
 
 // Creates an "extension" of an existing DIScope into another file.
-pub fn extend_scope_to_file(cx: &CodegenCx,
-                            scope_metadata: DIScope,
-                            file: &syntax_pos::FileMap,
-                            defining_crate: CrateNum)
-                            -> DILexicalBlock {
+pub fn extend_scope_to_file(
+    cx: &CodegenCx<'ll, '_>,
+    scope_metadata: &'ll DIScope,
+    file: &syntax_pos::FileMap,
+    defining_crate: CrateNum,
+) -> &'ll DILexicalBlock {
     let file_metadata = file_metadata(cx, &file.name, defining_crate);
     unsafe {
         llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
@@ -1720,9 +1762,11 @@ pub fn extend_scope_to_file(cx: &CodegenCx,
 /// given type.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                        ty: ty::Ty<'tcx>,
-                                        vtable: ValueRef) {
+pub fn create_vtable_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    ty: ty::Ty<'tcx>,
+    vtable: &'ll Value,
+) {
     if cx.dbg_cx.is_none() {
         return;
     }
@@ -1749,10 +1793,10 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             Size::ZERO.bits(),
             cx.tcx.data_layout.pointer_align.abi_bits() as u32,
             DIFlags::FlagArtificial,
-            ptr::null_mut(),
+            None,
             empty_array,
             0,
-            type_metadata,
+            Some(type_metadata),
             name.as_ptr()
         );
 
@@ -1771,7 +1815,7 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                                     vtable_type,
                                                     true,
                                                     vtable,
-                                                    ptr::null_mut(),
+                                                    None,
                                                     0);
     }
 }
index 9671db75baffeeb5b4c5db3c38dc57c24e1f1ed4..d4fb2549a752c80f6d03c287c8462dfb07bf180c 100644 (file)
@@ -21,8 +21,7 @@
 use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
 
 use llvm;
-use llvm::{ModuleRef, ContextRef, ValueRef};
-use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
+use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags};
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::{DefId, CrateNum};
 use rustc::ty::subst::{Substs, UnpackedKind};
 use monomorphize::Instance;
 use rustc::ty::{self, ParamEnv, Ty, InstanceDef};
 use rustc::mir;
-use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
+use rustc::session::config::{self, DebugInfo};
 use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
+use value::Value;
 
 use libc::c_uint;
 use std::cell::{Cell, RefCell};
 use std::ffi::CString;
-use std::ptr;
 
 use syntax_pos::{self, Span, Pos};
 use syntax::ast;
 const DW_TAG_arg_variable: c_uint = 0x101;
 
 /// A context object for maintaining all state needed by the debuginfo module.
-pub struct CrateDebugContext<'tcx> {
-    llcontext: ContextRef,
-    llmod: ModuleRef,
-    builder: DIBuilderRef,
-    created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>,
-    created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), DIType>>,
+pub struct CrateDebugContext<'a, 'tcx> {
+    llcontext: &'a llvm::Context,
+    llmod: &'a llvm::Module,
+    builder: &'a mut DIBuilder<'a>,
+    created_files: RefCell<FxHashMap<(Symbol, Symbol), &'a DIFile>>,
+    created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), &'a DIType>>,
 
-    type_map: RefCell<TypeMap<'tcx>>,
-    namespace_map: RefCell<DefIdMap<DIScope>>,
+    type_map: RefCell<TypeMap<'a, 'tcx>>,
+    namespace_map: RefCell<DefIdMap<&'a DIScope>>,
 
     // This collection is used to assert that composite types (structs, enums,
     // ...) have their members only set once:
-    composite_types_completed: RefCell<FxHashSet<DIType>>,
+    composite_types_completed: RefCell<FxHashSet<&'a DIType>>,
 }
 
-impl<'tcx> CrateDebugContext<'tcx> {
-    pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
+impl Drop for CrateDebugContext<'a, 'tcx> {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
+        }
+    }
+}
+
+impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
+    pub fn new(llmod: &'a llvm::Module) -> Self {
         debug!("CrateDebugContext::new");
         let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
         // DIBuilder inherits context from the module, so we'd better use the same one
@@ -101,14 +108,14 @@ pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
     }
 }
 
-pub enum FunctionDebugContext {
-    RegularContext(FunctionDebugContextData),
+pub enum FunctionDebugContext<'ll> {
+    RegularContext(FunctionDebugContextData<'ll>),
     DebugInfoDisabled,
     FunctionWithoutDebugInfo,
 }
 
-impl FunctionDebugContext {
-    pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData {
+impl FunctionDebugContext<'ll> {
+    pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData<'ll> {
         match *self {
             FunctionDebugContext::RegularContext(ref data) => data,
             FunctionDebugContext::DebugInfoDisabled => {
@@ -130,18 +137,18 @@ fn should_be_ignored_message() -> &'static str {
     }
 }
 
-pub struct FunctionDebugContextData {
-    fn_metadata: DISubprogram,
+pub struct FunctionDebugContextData<'ll> {
+    fn_metadata: &'ll DISubprogram,
     source_locations_enabled: Cell<bool>,
     pub defining_crate: CrateNum,
 }
 
-pub enum VariableAccess<'a> {
+pub enum VariableAccess<'a, 'll> {
     // The llptr given is an alloca containing the variable's value
-    DirectVariable { alloca: ValueRef },
+    DirectVariable { alloca: &'ll Value },
     // The llptr given is an alloca containing the start of some pointer chain
     // leading to the variable's content.
-    IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
+    IndirectVariable { alloca: &'ll Value, address_operations: &'a [i64] }
 }
 
 pub enum VariableKind {
@@ -167,7 +174,6 @@ pub fn finalize(cx: &CodegenCx) {
 
     unsafe {
         llvm::LLVMRustDIBuilderFinalize(DIB(cx));
-        llvm::LLVMRustDIBuilderDispose(DIB(cx));
         // Debuginfo generation in LLVM by default uses a higher
         // version of dwarf than macOS currently understands. We can
         // instruct LLVM to emit an older version of dwarf, however,
@@ -201,12 +207,14 @@ pub fn finalize(cx: &CodegenCx) {
 /// for debug info creation. The function may also return another variant of the
 /// FunctionDebugContext enum which indicates why no debuginfo should be created
 /// for the function.
-pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                               instance: Instance<'tcx>,
-                                               sig: ty::FnSig<'tcx>,
-                                               llfn: ValueRef,
-                                               mir: &mir::Mir) -> FunctionDebugContext {
-    if cx.sess().opts.debuginfo == NoDebugInfo {
+pub fn create_function_debug_context(
+    cx: &CodegenCx<'ll, 'tcx>,
+    instance: Instance<'tcx>,
+    sig: ty::FnSig<'tcx>,
+    llfn: &'ll Value,
+    mir: &mir::Mir,
+) -> FunctionDebugContext<'ll> {
+    if cx.sess().opts.debuginfo == DebugInfo::None {
         return FunctionDebugContext::DebugInfoDisabled;
     }
 
@@ -290,7 +298,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             cx.sess().opts.optimize != config::OptLevel::No,
             llfn,
             template_parameters,
-            ptr::null_mut())
+            None)
     };
 
     // Initialize fn debug context (including scope map and namespace map)
@@ -302,9 +310,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
     return FunctionDebugContext::RegularContext(fn_debug_context);
 
-    fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                        sig: ty::FnSig<'tcx>) -> DIArray {
-        if cx.sess().opts.debuginfo == LimitedDebugInfo {
+    fn get_function_signature(
+        cx: &CodegenCx<'ll, 'tcx>,
+        sig: ty::FnSig<'tcx>,
+    ) -> &'ll DIArray {
+        if cx.sess().opts.debuginfo == DebugInfo::Limited {
             return create_DIArray(DIB(cx), &[]);
         }
 
@@ -312,8 +322,8 @@ fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         // Return type -- llvm::DIBuilder wants this at index 0
         signature.push(match sig.output().sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
-            _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)
+            ty::TyTuple(ref tys) if tys.is_empty() => None,
+            _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP))
         });
 
         let inputs = if sig.abi == Abi::RustCall {
@@ -342,19 +352,20 @@ fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     }
                     _ => t
                 };
-                type_metadata(cx, t, syntax_pos::DUMMY_SP)
+                Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
             }));
         } else {
             signature.extend(inputs.iter().map(|t| {
-                type_metadata(cx, t, syntax_pos::DUMMY_SP)
+                Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
             }));
         }
 
         if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
             if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
                 signature.extend(
-                    args.iter().map(|argument_type|
-                        type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
+                    args.iter().map(|argument_type| {
+                        Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
+                    })
                 );
             }
         }
@@ -362,13 +373,13 @@ fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return create_DIArray(DIB(cx), &signature[..]);
     }
 
-    fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                         generics: &ty::Generics,
-                                         substs: &Substs<'tcx>,
-                                         file_metadata: DIFile,
-                                         name_to_append_suffix_to: &mut String)
-                                         -> DIArray
-    {
+    fn get_template_parameters(
+        cx: &CodegenCx<'ll, 'tcx>,
+        generics: &ty::Generics,
+        substs: &Substs<'tcx>,
+        file_metadata: &'ll DIFile,
+        name_to_append_suffix_to: &mut String,
+    ) -> &'ll DIArray {
         if substs.types().next().is_none() {
             return create_DIArray(DIB(cx), &[]);
         }
@@ -389,7 +400,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         name_to_append_suffix_to.push('>');
 
         // Again, only create type information if full debuginfo is enabled
-        let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
+        let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
             let names = get_parameter_names(cx, generics);
             substs.iter().zip(names).filter_map(|(kind, name)| {
                 if let UnpackedKind::Type(ty) = kind.unpack() {
@@ -398,14 +409,15 @@ fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                         type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
                     let name = CString::new(name.as_str().as_bytes()).unwrap();
                     Some(unsafe {
-                        llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
+                        Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                             DIB(cx),
-                            ptr::null_mut(),
+                            None,
                             name.as_ptr(),
                             actual_type_metadata,
                             file_metadata,
                             0,
-                            0)
+                            0,
+                        ))
                     })
                 } else {
                     None
@@ -428,9 +440,10 @@ fn get_parameter_names(cx: &CodegenCx,
         names
     }
 
-    fn get_containing_scope<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
-                                        instance: Instance<'tcx>)
-                                        -> DIScope {
+    fn get_containing_scope(
+        cx: &CodegenCx<'ll, 'tcx>,
+        instance: Instance<'tcx>,
+    ) -> &'ll DIScope {
         // First, let's see if this is a method within an inherent impl. Because
         // if yes, we want to make the result subroutine DIE a child of the
         // subroutine's self-type.
@@ -470,14 +483,16 @@ fn get_containing_scope<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
     }
 }
 
-pub fn declare_local<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                               dbg_context: &FunctionDebugContext,
-                               variable_name: ast::Name,
-                               variable_type: Ty<'tcx>,
-                               scope_metadata: DIScope,
-                               variable_access: VariableAccess,
-                               variable_kind: VariableKind,
-                               span: Span) {
+pub fn declare_local(
+    bx: &Builder<'a, 'll, 'tcx>,
+    dbg_context: &FunctionDebugContext<'ll>,
+    variable_name: ast::Name,
+    variable_type: Ty<'tcx>,
+    scope_metadata: &'ll DIScope,
+    variable_access: VariableAccess<'_, 'll>,
+    variable_kind: VariableKind,
+    span: Span,
+) {
     assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
     let cx = bx.cx;
 
index 51c45de9dc22a7633f1e8a6bdcaa35d5638acd28..9f1141a7e7db06cacf8d8f88472e5527cd6d587c 100644 (file)
@@ -22,7 +22,6 @@
 use common::CodegenCx;
 
 use std::ffi::CString;
-use std::ptr;
 
 pub fn mangled_name_of_instance<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
@@ -32,13 +31,13 @@ pub fn mangled_name_of_instance<'a, 'tcx>(
      tcx.symbol_name(instance)
 }
 
-pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
+pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
     if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) {
         return scope;
     }
 
     let def_key = cx.tcx.def_key(def_id);
-    let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| {
+    let parent_scope = def_key.parent.map(|parent| {
         item_namespace(cx, DefId {
             krate: def_id.krate,
             index: parent
index 958d09413edfaed93b4ec343fd3977a62c161243..55cf139394344d0e9a53f18467cca59ef9754e61 100644 (file)
 use builder::Builder;
 
 use libc::c_uint;
-use std::ptr;
 use syntax_pos::{Span, Pos};
 
 /// Sets the current debug location at the beginning of the span.
 ///
 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
 pub fn set_source_location(
-    debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span
+    debug_context: &FunctionDebugContext<'ll>,
+    bx: &Builder<'_, 'll, '_>,
+    scope: Option<&'ll DIScope>,
+    span: Span,
 ) {
     let function_debug_context = match *debug_context {
         FunctionDebugContext::DebugInfoDisabled => return,
@@ -40,7 +42,7 @@ pub fn set_source_location(
     let dbg_loc = if function_debug_context.source_locations_enabled.get() {
         debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span));
         let loc = span_start(bx.cx, span);
-        InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
+        InternalDebugLocation::new(scope.unwrap(), loc.line, loc.col.to_usize())
     } else {
         UnknownLocation
     };
@@ -53,7 +55,7 @@ pub fn set_source_location(
 /// they are disabled when beginning to codegen a new function. This functions
 /// switches source location emitting on and must therefore be called before the
 /// first real statement/expression of the function is codegened.
-pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
+pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext<'ll>) {
     match *dbg_context {
         FunctionDebugContext::RegularContext(ref data) => {
             data.source_locations_enabled.set(true)
@@ -64,13 +66,13 @@ pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
 
 
 #[derive(Copy, Clone, PartialEq)]
-pub enum InternalDebugLocation {
-    KnownLocation { scope: DIScope, line: usize, col: usize },
+pub enum InternalDebugLocation<'ll> {
+    KnownLocation { scope: &'ll DIScope, line: usize, col: usize },
     UnknownLocation
 }
 
-impl InternalDebugLocation {
-    pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
+impl InternalDebugLocation<'ll> {
+    pub fn new(scope: &'ll DIScope, line: usize, col: usize) -> Self {
         KnownLocation {
             scope,
             line,
@@ -79,7 +81,7 @@ pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
     }
 }
 
-pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
+pub fn set_debug_location(bx: &Builder<'_, 'll, '_>, debug_location: InternalDebugLocation<'ll>) {
     let metadata_node = match debug_location {
         KnownLocation { scope, line, col } => {
             // For MSVC, set the column number to zero.
@@ -93,17 +95,17 @@ pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
             debug!("setting debug location to {} {}", line, col);
 
             unsafe {
-                llvm::LLVMRustDIBuilderCreateDebugLocation(
+                Some(llvm::LLVMRustDIBuilderCreateDebugLocation(
                     debug_context(bx.cx).llcontext,
                     line as c_uint,
                     col_used,
                     scope,
-                    ptr::null_mut())
+                    None))
             }
         }
         UnknownLocation => {
             debug!("clearing debug location ");
-            ptr::null_mut()
+            None
         }
     };
 
index 9d37f99cb2a591f016538eb0b6bca3d91454f952..9f4a555082ad48452edb94b9ae68b80e5378a966 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::ty::DefIdTree;
 
 use llvm;
-use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
+use llvm::debuginfo::{DIScope, DIBuilder, DIDescriptor, DIArray};
 use common::{CodegenCx};
 
 use syntax_pos::{self, Span};
@@ -36,7 +36,10 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool
 }
 
 #[allow(non_snake_case)]
-pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
+pub fn create_DIArray(
+    builder: &DIBuilder<'ll>,
+    arr: &[Option<&'ll DIDescriptor>],
+) -> &'ll DIArray {
     return unsafe {
         llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
     };
@@ -48,18 +51,17 @@ pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc {
 }
 
 #[inline]
-pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>)
-                           -> &'a CrateDebugContext<'tcx> {
+pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> {
     cx.dbg_cx.as_ref().unwrap()
 }
 
 #[inline]
 #[allow(non_snake_case)]
-pub fn DIB(cx: &CodegenCx) -> DIBuilderRef {
+pub fn DIB(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> {
     cx.dbg_cx.as_ref().unwrap().builder
 }
 
-pub fn get_namespace_for_item(cx: &CodegenCx, def_id: DefId) -> DIScope {
+pub fn get_namespace_for_item(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
     item_namespace(cx, cx.tcx.parent(def_id)
         .expect("get_namespace_for_item: missing parent?"))
 }
index fdc84f914f50256dcc9fc03d558c694791b5b759..9812d7f9a41a21cc81ad0642606fa13e700b4505 100644 (file)
 //! Some useful guidelines:
 //!
 //! * Use declare_* family of methods if you are declaring, but are not
-//!   interested in defining the ValueRef they return.
-//! * Use define_* family of methods when you might be defining the ValueRef.
+//!   interested in defining the Value they return.
+//! * Use define_* family of methods when you might be defining the Value.
 //! * When in doubt, define.
 
-use llvm::{self, ValueRef};
+use llvm;
 use llvm::AttributePlace::Function;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, LayoutOf};
 /// Declare a global value.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// return its ValueRef instead.
-pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef {
+/// return its Value instead.
+pub fn declare_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> &'ll Value {
     debug!("declare_global(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
     unsafe {
-        llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty)
     }
 }
 
@@ -54,14 +54,19 @@ pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef {
 /// Declare a function.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// update the declaration and return existing ValueRef instead.
-fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
+/// update the declaration and return existing Value instead.
+fn declare_raw_fn(
+    cx: &CodegenCx<'ll, '_>,
+    name: &str,
+    callconv: llvm::CallConv,
+    ty: &'ll Type,
+) -> &'ll Value {
     debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
     let llfn = unsafe {
-        llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty.to_ref())
+        llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty)
     };
 
     llvm::SetFunctionCallConv(llfn, callconv);
@@ -114,8 +119,8 @@ fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type
 /// `declare_fn` instead.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// update the declaration and return existing ValueRef instead.
-pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef {
+/// update the declaration and return existing Value instead.
+pub fn declare_cfn(cx: &CodegenCx<'ll, '_>, name: &str, fn_type: &'ll Type) -> &'ll Value {
     declare_raw_fn(cx, name, llvm::CCallConv, fn_type)
 }
 
@@ -123,9 +128,12 @@ pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef {
 /// Declare a Rust function.
 ///
 /// If there’s a value with the same name already declared, the function will
-/// update the declaration and return existing ValueRef instead.
-pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
-                            fn_type: Ty<'tcx>) -> ValueRef {
+/// update the declaration and return existing Value instead.
+pub fn declare_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    fn_type: Ty<'tcx>,
+) -> &'ll Value {
     debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type);
     let sig = common::ty_fn_sig(cx, fn_type);
     let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
@@ -154,7 +162,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
 /// return None if the name already has a definition associated with it. In that
 /// case an error should be reported to the user, because it usually happens due
 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
-pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option<ValueRef> {
+pub fn define_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
     if get_defined_value(cx, name).is_some() {
         None
     } else {
@@ -167,9 +175,11 @@ pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option<ValueRef> {
 /// Use this function when you intend to define a function. This function will
 /// return panic if the name already has a definition associated with it. This
 /// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                           name: &str,
-                           fn_type: Ty<'tcx>) -> ValueRef {
+pub fn define_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    fn_type: Ty<'tcx>,
+) -> &'ll Value {
     if get_defined_value(cx, name).is_some() {
         cx.sess().fatal(&format!("symbol `{}` already defined", name))
     } else {
@@ -182,9 +192,11 @@ pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 /// Use this function when you intend to define a function. This function will
 /// return panic if the name already has a definition associated with it. This
 /// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                    name: &str,
-                                    fn_type: Ty<'tcx>) -> ValueRef {
+pub fn define_internal_fn(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    fn_type: Ty<'tcx>,
+) -> &'ll Value {
     let llfn = define_fn(cx, name, fn_type);
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
     llfn
@@ -192,24 +204,17 @@ pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
 
 /// Get declared value by name.
-pub fn get_declared_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+pub fn get_declared_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> {
     debug!("get_declared_value(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         bug!("name {:?} contains an interior null byte", name)
     });
-    let val = unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) };
-    if val.is_null() {
-        debug!("get_declared_value: {:?} value is null", name);
-        None
-    } else {
-        debug!("get_declared_value: {:?} => {:?}", name, Value(val));
-        Some(val)
-    }
+    unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) }
 }
 
 /// Get defined or externally defined (AvailableExternally linkage) value by
 /// name.
-pub fn get_defined_value(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+pub fn get_defined_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> {
     get_declared_value(cx, name).and_then(|val|{
         let declaration = unsafe {
             llvm::LLVMIsDeclaration(val) != 0
index c7275d094018567f7221192ea2cec1c20ecaf7a7..37ce51da778235f7e58a4a83ef7dcf52c0477126 100644 (file)
 
 use builder::Builder;
 use common::*;
-use llvm::{ValueRef};
 use llvm;
 use meth;
 use rustc::ty::layout::LayoutOf;
 use rustc::ty::{self, Ty};
 use value::Value;
 
-pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
-                                       -> (ValueRef, ValueRef) {
+pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Option<&'ll Value>)
+                                       -> (&'ll Value, &'ll Value) {
     debug!("calculate size of DST: {}; with lost info: {:?}",
-           t, Value(info));
+           t, info);
     if bx.cx.type_is_sized(t) {
         let (size, align) = bx.cx.size_and_align_of(t);
         debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
-               t, Value(info), size, align);
+               t, info, size, align);
         let size = C_usize(bx.cx, size.bytes());
         let align = C_usize(bx.cx, align.abi());
         return (size, align);
     }
-    assert!(!info.is_null());
     match t.sty {
         ty::TyDynamic(..) => {
             // load size/align from vtable
-            (meth::SIZE.get_usize(bx, info), meth::ALIGN.get_usize(bx, info))
+            let vtable = info.unwrap();
+            (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
         }
         ty::TySlice(_) | ty::TyStr => {
             let unit = t.sequence_element_type(bx.tcx());
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
             let (size, align) = bx.cx.size_and_align_of(unit);
-            (bx.mul(info, C_usize(bx.cx, size.bytes())),
+            (bx.mul(info.unwrap(), C_usize(bx.cx, size.bytes())),
              C_usize(bx.cx, align.abi()))
         }
         _ => {
index 9c5c0f730c161e8e8eb6a4fed1989a6e0c178c43..0b5a6757333f252c2c32b4b993c7bd5322b5c477 100644 (file)
@@ -11,8 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use intrinsics::{self, Intrinsic};
-use llvm;
-use llvm::{ValueRef};
+use llvm::{self, TypeKind};
 use abi::{Abi, FnType, LlvmType, PassMode};
 use mir::place::PlaceRef;
 use mir::operand::{OperandRef, OperandValue};
@@ -28,6 +27,7 @@
 use syntax::ast;
 use syntax::symbol::Symbol;
 use builder::Builder;
+use value::Value;
 
 use rustc::session::Session;
 use syntax_pos::Span;
@@ -35,7 +35,7 @@
 use std::cmp::Ordering;
 use std::iter;
 
-fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
+fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> {
     let llvm_name = match name {
         "sqrtf32" => "llvm.sqrt.f32",
         "sqrtf64" => "llvm.sqrt.f64",
@@ -85,12 +85,14 @@ fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
 /// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
 /// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
 /// add them to librustc_codegen_llvm/context.rs
-pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                                      callee_ty: Ty<'tcx>,
-                                      fn_ty: &FnType<'tcx, Ty<'tcx>>,
-                                      args: &[OperandRef<'tcx>],
-                                      llresult: ValueRef,
-                                      span: Span) {
+pub fn codegen_intrinsic_call(
+    bx: &Builder<'a, 'll, 'tcx>,
+    callee_ty: Ty<'tcx>,
+    fn_ty: &FnType<'tcx, Ty<'tcx>>,
+    args: &[OperandRef<'ll, 'tcx>],
+    llresult: &'ll Value,
+    span: Span,
+) {
     let cx = bx.cx;
     let tcx = cx.tcx;
 
@@ -146,7 +148,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             let tp_ty = substs.type_at(0);
             if let OperandValue::Pair(_, meta) = args[0].val {
                 let (llsize, _) =
-                    glue::size_and_align_of_dst(bx, tp_ty, meta);
+                    glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
                 llsize
             } else {
                 C_usize(cx, cx.size_of(tp_ty).bytes())
@@ -160,7 +162,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             let tp_ty = substs.type_at(0);
             if let OperandValue::Pair(_, meta) = args[0].val {
                 let (_, llalign) =
-                    glue::size_and_align_of_dst(bx, tp_ty, meta);
+                    glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
                 llalign
             } else {
                 C_usize(cx, cx.align_of(tp_ty).abi())
@@ -545,7 +547,7 @@ fn one<T>(x: Vec<T>) -> T {
                 assert_eq!(x.len(), 1);
                 x.into_iter().next().unwrap()
             }
-            fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec<Type> {
+            fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> {
                 use intrinsics::Type::*;
                 match *t {
                     Void => vec![Type::void(cx)],
@@ -567,7 +569,7 @@ fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec<Type> {
                     Vector(ref t, ref llvm_elem, length) => {
                         let t = llvm_elem.as_ref().unwrap_or(t);
                         let elem = one(ty_to_type(cx, t));
-                        vec![Type::vector(&elem, length as u64)]
+                        vec![Type::vector(elem, length as u64)]
                     }
                     Aggregate(false, ref contents) => {
                         let elems = contents.iter()
@@ -587,11 +589,11 @@ fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec<Type> {
             // qux` to be converted into `foo, bar, baz, qux`, integer
             // arguments to be truncated as needed and pointers to be
             // cast.
-            fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                                          t: &intrinsics::Type,
-                                          arg: &OperandRef<'tcx>)
-                                          -> Vec<ValueRef>
-            {
+            fn modify_as_needed(
+                bx: &Builder<'a, 'll, 'tcx>,
+                t: &intrinsics::Type,
+                arg: &OperandRef<'ll, 'tcx>,
+            ) -> Vec<&'ll Value> {
                 match *t {
                     intrinsics::Type::Aggregate(true, ref contents) => {
                         // We found a tuple that needs squishing! So
@@ -616,7 +618,7 @@ fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                     }
                     intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => {
                         let llvm_elem = one(ty_to_type(bx.cx, llvm_elem));
-                        vec![bx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))]
+                        vec![bx.bitcast(arg.immediate(), Type::vector(llvm_elem, length as u64))]
                     }
                     intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
                         // the LLVM intrinsic uses a smaller integer
@@ -644,7 +646,7 @@ fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                 intrinsics::IntrinsicDef::Named(name) => {
                     let f = declare::declare_cfn(cx,
                                                  name,
-                                                 Type::func(&inputs, &outputs));
+                                                 Type::func(&inputs, outputs));
                     bx.call(f, &llargs, None)
                 }
             };
@@ -677,14 +679,15 @@ fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
     }
 }
 
-fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                            allow_overlap: bool,
-                            volatile: bool,
-                            ty: Ty<'tcx>,
-                            dst: ValueRef,
-                            src: ValueRef,
-                            count: ValueRef)
-                            -> ValueRef {
+fn copy_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
+    allow_overlap: bool,
+    volatile: bool,
+    ty: Ty<'tcx>,
+    dst: &'ll Value,
+    src: &'ll Value,
+    count: &'ll Value,
+) -> &'ll Value {
     let cx = bx.cx;
     let (size, align) = cx.size_and_align_of(ty);
     let size = C_usize(cx, size.bytes());
@@ -712,14 +715,14 @@ fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
         None)
 }
 
-fn memset_intrinsic<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
+fn memset_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
     volatile: bool,
     ty: Ty<'tcx>,
-    dst: ValueRef,
-    val: ValueRef,
-    count: ValueRef
-) -> ValueRef {
+    dst: &'ll Value,
+    val: &'ll Value,
+    count: &'ll Value
+) -> &'ll Value {
     let cx = bx.cx;
     let (size, align) = cx.size_and_align_of(ty);
     let size = C_usize(cx, size.bytes());
@@ -728,13 +731,13 @@ fn memset_intrinsic<'a, 'tcx>(
     call_memset(bx, dst, val, bx.mul(size, count), align, volatile)
 }
 
-fn try_intrinsic<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
-    cx: &CodegenCx,
-    func: ValueRef,
-    data: ValueRef,
-    local_ptr: ValueRef,
-    dest: ValueRef,
+fn try_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
+    cx: &CodegenCx<'ll, 'tcx>,
+    func: &'ll Value,
+    data: &'ll Value,
+    local_ptr: &'ll Value,
+    dest: &'ll Value,
 ) {
     if bx.sess().no_landing_pads() {
         bx.call(func, &[data], None);
@@ -754,12 +757,14 @@ fn try_intrinsic<'a, 'tcx>(
 // instructions are meant to work for all targets, as of the time of this
 // writing, however, LLVM does not recommend the usage of these new instructions
 // as the old ones are still more optimized.
-fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                            cx: &CodegenCx,
-                            func: ValueRef,
-                            data: ValueRef,
-                            local_ptr: ValueRef,
-                            dest: ValueRef) {
+fn codegen_msvc_try(
+    bx: &Builder<'a, 'll, 'tcx>,
+    cx: &CodegenCx<'ll, 'tcx>,
+    func: &'ll Value,
+    data: &'ll Value,
+    local_ptr: &'ll Value,
+    dest: &'ll Value,
+) {
     let llfn = get_rust_try_fn(cx, &mut |bx| {
         let cx = bx.cx;
 
@@ -862,12 +867,14 @@ fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 // function calling it, and that function may already have other personality
 // functions in play. By calling a shim we're guaranteed that our shim will have
 // the right personality function.
-fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                           cx: &CodegenCx,
-                           func: ValueRef,
-                           data: ValueRef,
-                           local_ptr: ValueRef,
-                           dest: ValueRef) {
+fn codegen_gnu_try(
+    bx: &Builder<'a, 'll, 'tcx>,
+    cx: &CodegenCx<'ll, 'tcx>,
+    func: &'ll Value,
+    data: &'ll Value,
+    local_ptr: &'ll Value,
+    dest: &'ll Value,
+) {
     let llfn = get_rust_try_fn(cx, &mut |bx| {
         let cx = bx.cx;
 
@@ -922,12 +929,13 @@ fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
 // Helper function to give a Block to a closure to codegen a shim function.
 // This is currently primarily used for the `try` intrinsic functions above.
-fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                    name: &str,
-                    inputs: Vec<Ty<'tcx>>,
-                    output: Ty<'tcx>,
-                    codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>))
-                    -> ValueRef {
+fn gen_fn<'ll, 'tcx>(
+    cx: &CodegenCx<'ll, 'tcx>,
+    name: &str,
+    inputs: Vec<Ty<'tcx>>,
+    output: Ty<'tcx>,
+    codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
+) -> &'ll Value {
     let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig(
         inputs.into_iter(),
         output,
@@ -945,9 +953,10 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 // catch exceptions.
 //
 // This function is only generated once and is then cached.
-fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                             codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>))
-                             -> ValueRef {
+fn get_rust_try_fn<'ll, 'tcx>(
+    cx: &CodegenCx<'ll, 'tcx>,
+    codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
+) -> &'ll Value {
     if let Some(llfn) = cx.rust_try_fn.get() {
         return llfn;
     }
@@ -972,15 +981,15 @@ fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
     span_err!(a, b, E0511, "{}", c);
 }
 
-fn generic_simd_intrinsic<'a, 'tcx>(
-    bx: &Builder<'a, 'tcx>,
+fn generic_simd_intrinsic(
+    bx: &Builder<'a, 'll, 'tcx>,
     name: &str,
     callee_ty: Ty<'tcx>,
-    args: &[OperandRef<'tcx>],
+    args: &[OperandRef<'ll, 'tcx>],
     ret_ty: Ty<'tcx>,
-    llret_ty: Type,
+    llret_ty: &'ll Type,
     span: Span
-) -> Result<ValueRef, ()> {
+) -> Result<&'ll Value, ()> {
     // macros for error handling:
     macro_rules! emit_error {
         ($msg: tt) => {
@@ -1050,7 +1059,7 @@ macro_rules! require_simd {
                   found `{}` with length {}",
                  in_len, in_ty,
                  ret_ty, out_len);
-        require!(llret_ty.element_type().kind() == llvm::Integer,
+        require!(llret_ty.element_type().kind() == TypeKind::Integer,
                  "expected return type with integer elements, found `{}` with non-integer `{}`",
                  ret_ty,
                  ret_ty.simd_type(tcx));
@@ -1145,19 +1154,20 @@ macro_rules! require_simd {
         }
         // truncate the mask to a vector of i1s
         let i1 = Type::i1(bx.cx);
-        let i1xn = Type::vector(&i1, m_len as u64);
+        let i1xn = Type::vector(i1, m_len as u64);
         let m_i1s = bx.trunc(args[0].immediate(), i1xn);
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
 
-    fn simd_simple_float_intrinsic<'a, 'tcx>(name: &str,
-                                             in_elem: &::rustc::ty::TyS,
-                                             in_ty: &::rustc::ty::TyS,
-                                             in_len: usize,
-                                             bx: &Builder<'a, 'tcx>,
-                                             span: Span,
-                                             args: &[OperandRef<'tcx>])
-                                             -> Result<ValueRef, ()> {
+    fn simd_simple_float_intrinsic(
+        name: &str,
+        in_elem: &::rustc::ty::TyS,
+        in_ty: &::rustc::ty::TyS,
+        in_len: usize,
+        bx: &Builder<'a, 'll, 'tcx>,
+        span: Span,
+        args: &[OperandRef<'ll, 'tcx>],
+    ) -> Result<&'ll Value, ()> {
         macro_rules! emit_error {
             ($msg: tt) => {
                 emit_error!($msg, )
@@ -1283,8 +1293,8 @@ fn llvm_vector_str(elem_ty: ty::Ty, vec_len: usize, no_pointers: usize) -> Strin
         }
     }
 
-    fn llvm_vector_ty(cx: &CodegenCx, elem_ty: ty::Ty, vec_len: usize,
-                      mut no_pointers: usize) -> Type {
+    fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize,
+                      mut no_pointers: usize) -> &'ll Type {
         // FIXME: use cx.layout_of(ty).llvm_type() ?
         let mut elem_ty = match elem_ty.sty {
             ty::TyInt(v) => Type::int_from_ty(cx, v),
@@ -1296,7 +1306,7 @@ fn llvm_vector_ty(cx: &CodegenCx, elem_ty: ty::Ty, vec_len: usize,
             elem_ty = elem_ty.ptr_to();
             no_pointers -= 1;
         }
-        Type::vector(&elem_ty, vec_len as u64)
+        Type::vector(elem_ty, vec_len as u64)
     }
 
 
@@ -1379,7 +1389,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
         // Truncate the mask vector to a vector of i1s:
         let (mask, mask_ty) = {
             let i1 = Type::i1(bx.cx);
-            let i1xn = Type::vector(&i1, in_len as u64);
+            let i1xn = Type::vector(i1, in_len as u64);
             (bx.trunc(args[2].immediate(), i1xn), i1xn)
         };
 
@@ -1395,7 +1405,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
                                      llvm_elem_vec_str, llvm_pointer_vec_str);
         let f = declare::declare_cfn(bx.cx, &llvm_intrinsic,
                                      Type::func(&[llvm_pointer_vec_ty, alignment_ty, mask_ty,
-                                                  llvm_elem_vec_ty], &llvm_elem_vec_ty));
+                                                  llvm_elem_vec_ty], llvm_elem_vec_ty));
         llvm::SetUnnamedAddr(f, false);
         let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()],
                         None);
@@ -1476,7 +1486,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
         // Truncate the mask vector to a vector of i1s:
         let (mask, mask_ty) = {
             let i1 = Type::i1(bx.cx);
-            let i1xn = Type::vector(&i1, in_len as u64);
+            let i1xn = Type::vector(i1, in_len as u64);
             (bx.trunc(args[2].immediate(), i1xn), i1xn)
         };
 
@@ -1496,7 +1506,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty {
                                      Type::func(&[llvm_elem_vec_ty,
                                                   llvm_pointer_vec_ty,
                                                   alignment_ty,
-                                                  mask_ty], &ret_t));
+                                                  mask_ty], ret_t));
         llvm::SetUnnamedAddr(f, false);
         let v = bx.call(f, &[args[0].immediate(), args[1].immediate(), alignment, mask],
                         None);
@@ -1629,7 +1639,7 @@ macro_rules! bitwise_red {
 
                     // boolean reductions operate on vectors of i1s:
                     let i1 = Type::i1(bx.cx);
-                    let i1xn = Type::vector(&i1, in_len as u64);
+                    let i1xn = Type::vector(i1, in_len as u64);
                     bx.trunc(args[0].immediate(), i1xn)
                 };
                 return match in_elem.sty {
@@ -1768,14 +1778,7 @@ macro_rules! arith {
 fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
     match ty.sty {
         ty::TyInt(t) => Some((match t {
-            ast::IntTy::Isize => {
-                match &cx.tcx.sess.target.target.target_pointer_width[..] {
-                    "16" => 16,
-                    "32" => 32,
-                    "64" => 64,
-                    tws => bug!("Unsupported target word size for isize: {}", tws),
-                }
-            },
+            ast::IntTy::Isize => cx.tcx.sess.target.isize_ty.bit_width().unwrap() as u64,
             ast::IntTy::I8 => 8,
             ast::IntTy::I16 => 16,
             ast::IntTy::I32 => 32,
@@ -1783,14 +1786,7 @@ fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
             ast::IntTy::I128 => 128,
         }, true)),
         ty::TyUint(t) => Some((match t {
-            ast::UintTy::Usize => {
-                match &cx.tcx.sess.target.target.target_pointer_width[..] {
-                    "16" => 16,
-                    "32" => 32,
-                    "64" => 64,
-                    tws => bug!("Unsupported target word size for usize: {}", tws),
-                }
-            },
+            ast::UintTy::Usize => cx.tcx.sess.target.usize_ty.bit_width().unwrap() as u64,
             ast::UintTy::U8 => 8,
             ast::UintTy::U16 => 16,
             ast::UintTy::U32 => 32,
@@ -1803,14 +1799,9 @@ fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> {
 
 // Returns the width of a float TypeVariant
 // Returns None if the type is not a float
-fn float_type_width<'tcx>(sty: &ty::TypeVariants<'tcx>)
-        -> Option<u64> {
-    use rustc::ty::TyFloat;
+fn float_type_width<'tcx>(sty: &ty::TypeVariants<'tcx>) -> Option<u64> {
     match *sty {
-        TyFloat(t) => Some(match t {
-            ast::FloatTy::F32 => 32,
-            ast::FloatTy::F64 => 64,
-        }),
+        ty::TyFloat(t) => Some(t.bit_width() as u64),
         _ => None,
     }
 }
index 90f96c9687bc146de2642a2a90e0f729c9ac8875..c01ef37d1b8cca664653b8e90d249c09f51d2680 100644 (file)
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
 #![feature(custom_attribute)]
+#![feature(extern_types)]
 #![feature(fs_read_write)]
+#![feature(in_band_lifetimes)]
 #![allow(unused_attributes)]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(optin_builtin_traits)]
+#![feature(concat_idents)]
+#![feature(link_args)]
+#![feature(static_nobundle)]
 
+use back::write::create_target_machine;
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 
@@ -46,7 +53,7 @@
 #[macro_use] extern crate rustc_data_structures;
 extern crate rustc_demangle;
 extern crate rustc_incremental;
-extern crate rustc_llvm as llvm;
+extern crate rustc_llvm;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate rustc_codegen_utils;
 
@@ -77,6 +84,7 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::util::time_graph;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
+use rustc::util::profiling::ProfileCategory;
 use rustc_mir::monomorphize;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 
@@ -110,6 +118,7 @@ mod back {
 mod declare;
 mod glue;
 mod intrinsic;
+pub mod llvm;
 mod llvm_util;
 mod metadata;
 mod meth;
@@ -232,10 +241,12 @@ fn join_codegen_and_link(
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
+        sess.profiler(|p| p.start_activity(ProfileCategory::Linking));
         time(sess, "linking", || {
             back::link::link_binary(sess, &ongoing_codegen,
                                     outputs, &ongoing_codegen.crate_name.as_str());
         });
+        sess.profiler(|p| p.end_activity(ProfileCategory::Linking));
 
         // Now that we won't touch anything in the incremental compilation directory
         // any more, we can finalize it (which involves renaming it)
@@ -335,22 +346,41 @@ enum ModuleSource {
     Codegened(ModuleLlvm),
 }
 
-#[derive(Debug)]
 struct ModuleLlvm {
-    llcx: llvm::ContextRef,
-    llmod: llvm::ModuleRef,
-    tm: llvm::TargetMachineRef,
+    llcx: &'static mut llvm::Context,
+    llmod_raw: *const llvm::Module,
+    tm: &'static mut llvm::TargetMachine,
 }
 
 unsafe impl Send for ModuleLlvm { }
 unsafe impl Sync for ModuleLlvm { }
 
+impl ModuleLlvm {
+    fn new(sess: &Session, mod_name: &str) -> Self {
+        unsafe {
+            let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
+            let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _;
+
+            ModuleLlvm {
+                llmod_raw,
+                llcx,
+                tm: create_target_machine(sess, false),
+            }
+        }
+    }
+
+    fn llmod(&self) -> &llvm::Module {
+        unsafe {
+            &*self.llmod_raw
+        }
+    }
+}
+
 impl Drop for ModuleLlvm {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeModule(self.llmod);
-            llvm::LLVMContextDispose(self.llcx);
-            llvm::LLVMRustDisposeTargetMachine(self.tm);
+            llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
+            llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
         }
     }
 }
diff --git a/src/librustc_codegen_llvm/llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs
new file mode 100644 (file)
index 0000000..4cbf0d9
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A wrapper around LLVM's archive (.a) code
+
+use std::ffi::CString;
+use std::path::Path;
+use std::slice;
+use std::str;
+
+pub struct ArchiveRO {
+    pub raw: &'static mut super::Archive,
+}
+
+unsafe impl Send for ArchiveRO {}
+
+pub struct Iter<'a> {
+    raw: &'a mut super::ArchiveIterator<'a>,
+}
+
+pub struct Child<'a> {
+    pub raw: &'a mut super::ArchiveChild<'a>,
+}
+
+impl ArchiveRO {
+    /// Opens a static archive for read-only purposes. This is more optimized
+    /// than the `open` method because it uses LLVM's internal `Archive` class
+    /// rather than shelling out to `ar` for everything.
+    ///
+    /// If this archive is used with a mutable method, then an error will be
+    /// raised.
+    pub fn open(dst: &Path) -> Result<ArchiveRO, String> {
+        return unsafe {
+            let s = path2cstr(dst);
+            let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| {
+                super::last_error().unwrap_or("failed to open archive".to_string())
+            })?;
+            Ok(ArchiveRO { raw: ar })
+        };
+
+        #[cfg(unix)]
+        fn path2cstr(p: &Path) -> CString {
+            use std::os::unix::prelude::*;
+            use std::ffi::OsStr;
+            let p: &OsStr = p.as_ref();
+            CString::new(p.as_bytes()).unwrap()
+        }
+        #[cfg(windows)]
+        fn path2cstr(p: &Path) -> CString {
+            CString::new(p.to_str().unwrap()).unwrap()
+        }
+    }
+
+    pub fn iter(&self) -> Iter {
+        unsafe {
+            Iter {
+                raw: super::LLVMRustArchiveIteratorNew(self.raw),
+            }
+        }
+    }
+}
+
+impl Drop for ArchiveRO {
+    fn drop(&mut self) {
+        unsafe {
+            super::LLVMRustDestroyArchive(&mut *(self.raw as *mut _));
+        }
+    }
+}
+
+impl<'a> Iterator for Iter<'a> {
+    type Item = Result<Child<'a>, String>;
+
+    fn next(&mut self) -> Option<Result<Child<'a>, String>> {
+        unsafe {
+            match super::LLVMRustArchiveIteratorNext(self.raw) {
+                Some(raw) => Some(Ok(Child { raw })),
+                None => super::last_error().map(Err),
+            }
+        }
+    }
+}
+
+impl<'a> Drop for Iter<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            super::LLVMRustArchiveIteratorFree(&mut *(self.raw as *mut _));
+        }
+    }
+}
+
+impl<'a> Child<'a> {
+    pub fn name(&self) -> Option<&'a str> {
+        unsafe {
+            let mut name_len = 0;
+            let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len);
+            if name_ptr.is_null() {
+                None
+            } else {
+                let name = slice::from_raw_parts(name_ptr as *const u8, name_len as usize);
+                str::from_utf8(name).ok().map(|s| s.trim())
+            }
+        }
+    }
+
+    pub fn data(&self) -> &'a [u8] {
+        unsafe {
+            let mut data_len = 0;
+            let data_ptr = super::LLVMRustArchiveChildData(self.raw, &mut data_len);
+            if data_ptr.is_null() {
+                panic!("failed to read data from archive child");
+            }
+            slice::from_raw_parts(data_ptr as *const u8, data_len as usize)
+        }
+    }
+}
+
+impl<'a> Drop for Child<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            super::LLVMRustArchiveChildFree(&mut *(self.raw as *mut _));
+        }
+    }
+}
diff --git a/src/librustc_codegen_llvm/llvm/diagnostic.rs b/src/librustc_codegen_llvm/llvm/diagnostic.rs
new file mode 100644 (file)
index 0000000..c41a5f7
--- /dev/null
@@ -0,0 +1,179 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! LLVM diagnostic reports.
+
+pub use self::OptimizationDiagnosticKind::*;
+pub use self::Diagnostic::*;
+
+use libc::c_uint;
+use value::Value;
+
+use super::{DiagnosticInfo, Twine};
+
+#[derive(Copy, Clone)]
+pub enum OptimizationDiagnosticKind {
+    OptimizationRemark,
+    OptimizationMissed,
+    OptimizationAnalysis,
+    OptimizationAnalysisFPCommute,
+    OptimizationAnalysisAliasing,
+    OptimizationFailure,
+    OptimizationRemarkOther,
+}
+
+impl OptimizationDiagnosticKind {
+    pub fn describe(self) -> &'static str {
+        match self {
+            OptimizationRemark | OptimizationRemarkOther => "remark",
+            OptimizationMissed => "missed",
+            OptimizationAnalysis => "analysis",
+            OptimizationAnalysisFPCommute => "floating-point",
+            OptimizationAnalysisAliasing => "aliasing",
+            OptimizationFailure => "failure",
+        }
+    }
+}
+
+pub struct OptimizationDiagnostic<'ll> {
+    pub kind: OptimizationDiagnosticKind,
+    pub pass_name: String,
+    pub function: &'ll Value,
+    pub line: c_uint,
+    pub column: c_uint,
+    pub filename: String,
+    pub message: String,
+}
+
+impl OptimizationDiagnostic<'ll> {
+    unsafe fn unpack(
+        kind: OptimizationDiagnosticKind,
+        di: &'ll DiagnosticInfo,
+    ) -> Self {
+        let mut function = None;
+        let mut line = 0;
+        let mut column = 0;
+
+        let mut message = None;
+        let mut filename = None;
+        let pass_name = super::build_string(|pass_name|
+            message = super::build_string(|message|
+                filename = super::build_string(|filename|
+                    super::LLVMRustUnpackOptimizationDiagnostic(di,
+                                                                pass_name,
+                                                                &mut function,
+                                                                &mut line,
+                                                                &mut column,
+                                                                filename,
+                                                                message)
+                ).ok()
+            ).ok()
+        ).ok();
+
+        let mut filename = filename.unwrap_or(String::new());
+        if filename.is_empty() {
+            filename.push_str("<unknown file>");
+        }
+
+        OptimizationDiagnostic {
+            kind,
+            pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
+            function: function.unwrap(),
+            line,
+            column,
+            filename,
+            message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM")
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct InlineAsmDiagnostic<'ll> {
+    pub cookie: c_uint,
+    pub message: &'ll Twine,
+    pub instruction: &'ll Value,
+}
+
+impl InlineAsmDiagnostic<'ll> {
+    unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
+        let mut cookie = 0;
+        let mut message = None;
+        let mut instruction = None;
+
+        super::LLVMRustUnpackInlineAsmDiagnostic(
+            di,
+            &mut cookie,
+            &mut message,
+            &mut instruction,
+        );
+
+        InlineAsmDiagnostic {
+            cookie,
+            message: message.unwrap(),
+            instruction: instruction.unwrap(),
+        }
+    }
+}
+
+pub enum Diagnostic<'ll> {
+    Optimization(OptimizationDiagnostic<'ll>),
+    InlineAsm(InlineAsmDiagnostic<'ll>),
+    PGO(&'ll DiagnosticInfo),
+    Linker(&'ll DiagnosticInfo),
+
+    /// LLVM has other types that we do not wrap here.
+    UnknownDiagnostic(&'ll DiagnosticInfo),
+}
+
+impl Diagnostic<'ll> {
+    pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
+        use super::DiagnosticKind as Dk;
+        let kind = super::LLVMRustGetDiagInfoKind(di);
+
+        match kind {
+            Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
+
+            Dk::OptimizationRemark => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
+            }
+            Dk::OptimizationRemarkOther => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
+            }
+            Dk::OptimizationRemarkMissed => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
+            }
+
+            Dk::OptimizationRemarkAnalysis => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
+            }
+
+            Dk::OptimizationRemarkAnalysisFPCommute => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
+            }
+
+            Dk::OptimizationRemarkAnalysisAliasing => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
+            }
+
+            Dk::OptimizationFailure => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
+            }
+
+            Dk::PGOProfile => {
+                PGO(di)
+            }
+            Dk::Linker => {
+                Linker(di)
+            }
+
+            _ => UnknownDiagnostic(di),
+        }
+    }
+}
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
new file mode 100644 (file)
index 0000000..989498e
--- /dev/null
@@ -0,0 +1,1634 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression'
+// once support for LLVM 3.9 is dropped.
+//
+// This method was changed in this LLVM patch:
+// https://reviews.llvm.org/D26769
+
+use super::debuginfo::{
+    DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
+    DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
+    DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
+    DINameSpace, DIFlags,
+};
+
+use libc::{c_uint, c_int, size_t, c_char};
+use libc::{c_ulonglong, c_void};
+
+use std::marker::PhantomData;
+
+use super::RustString;
+
+pub type Bool = c_uint;
+
+pub const True: Bool = 1 as Bool;
+pub const False: Bool = 0 as Bool;
+
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+#[allow(dead_code)] // Variants constructed by C++.
+pub enum LLVMRustResult {
+    Success,
+    Failure,
+}
+// Consts for the LLVM CallConv type, pre-cast to usize.
+
+/// LLVM CallingConv::ID. Should we wrap this?
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum CallConv {
+    CCallConv = 0,
+    FastCallConv = 8,
+    ColdCallConv = 9,
+    X86StdcallCallConv = 64,
+    X86FastcallCallConv = 65,
+    ArmAapcsCallConv = 67,
+    Msp430Intr = 69,
+    X86_ThisCall = 70,
+    PtxKernel = 71,
+    X86_64_SysV = 78,
+    X86_64_Win64 = 79,
+    X86_VectorCall = 80,
+    X86_Intr = 83,
+    AmdGpuKernel = 91,
+}
+
+/// LLVMRustLinkage
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[repr(C)]
+pub enum Linkage {
+    ExternalLinkage = 0,
+    AvailableExternallyLinkage = 1,
+    LinkOnceAnyLinkage = 2,
+    LinkOnceODRLinkage = 3,
+    WeakAnyLinkage = 4,
+    WeakODRLinkage = 5,
+    AppendingLinkage = 6,
+    InternalLinkage = 7,
+    PrivateLinkage = 8,
+    ExternalWeakLinkage = 9,
+    CommonLinkage = 10,
+}
+
+// LLVMRustVisibility
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[repr(C)]
+pub enum Visibility {
+    Default = 0,
+    Hidden = 1,
+    Protected = 2,
+}
+
+/// LLVMDLLStorageClass
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum DLLStorageClass {
+    #[allow(dead_code)]
+    Default = 0,
+    DllImport = 1, // Function to be imported from DLL.
+    #[allow(dead_code)]
+    DllExport = 2, // Function to be accessible from DLL.
+}
+
+/// Matches LLVMRustAttribute in rustllvm.h
+/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
+/// though it is not ABI compatible (since it's a C++ enum)
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub enum Attribute {
+    AlwaysInline    = 0,
+    ByVal           = 1,
+    Cold            = 2,
+    InlineHint      = 3,
+    MinSize         = 4,
+    Naked           = 5,
+    NoAlias         = 6,
+    NoCapture       = 7,
+    NoInline        = 8,
+    NonNull         = 9,
+    NoRedZone       = 10,
+    NoReturn        = 11,
+    NoUnwind        = 12,
+    OptimizeForSize = 13,
+    ReadOnly        = 14,
+    SExt            = 15,
+    StructRet       = 16,
+    UWTable         = 17,
+    ZExt            = 18,
+    InReg           = 19,
+    SanitizeThread  = 20,
+    SanitizeAddress = 21,
+    SanitizeMemory  = 22,
+}
+
+/// LLVMIntPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum IntPredicate {
+    IntEQ = 32,
+    IntNE = 33,
+    IntUGT = 34,
+    IntUGE = 35,
+    IntULT = 36,
+    IntULE = 37,
+    IntSGT = 38,
+    IntSGE = 39,
+    IntSLT = 40,
+    IntSLE = 41,
+}
+
+/// LLVMRealPredicate
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum RealPredicate {
+    RealPredicateFalse = 0,
+    RealOEQ = 1,
+    RealOGT = 2,
+    RealOGE = 3,
+    RealOLT = 4,
+    RealOLE = 5,
+    RealONE = 6,
+    RealORD = 7,
+    RealUNO = 8,
+    RealUEQ = 9,
+    RealUGT = 10,
+    RealUGE = 11,
+    RealULT = 12,
+    RealULE = 13,
+    RealUNE = 14,
+    RealPredicateTrue = 15,
+}
+
+/// LLVMTypeKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+pub enum TypeKind {
+    Void = 0,
+    Half = 1,
+    Float = 2,
+    Double = 3,
+    X86_FP80 = 4,
+    FP128 = 5,
+    PPC_FP128 = 6,
+    Label = 7,
+    Integer = 8,
+    Function = 9,
+    Struct = 10,
+    Array = 11,
+    Pointer = 12,
+    Vector = 13,
+    Metadata = 14,
+    X86_MMX = 15,
+    Token = 16,
+}
+
+/// LLVMAtomicRmwBinOp
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicRmwBinOp {
+    AtomicXchg = 0,
+    AtomicAdd = 1,
+    AtomicSub = 2,
+    AtomicAnd = 3,
+    AtomicNand = 4,
+    AtomicOr = 5,
+    AtomicXor = 6,
+    AtomicMax = 7,
+    AtomicMin = 8,
+    AtomicUMax = 9,
+    AtomicUMin = 10,
+}
+
+/// LLVMAtomicOrdering
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AtomicOrdering {
+    #[allow(dead_code)]
+    NotAtomic = 0,
+    Unordered = 1,
+    Monotonic = 2,
+    // Consume = 3,  // Not specified yet.
+    Acquire = 4,
+    Release = 5,
+    AcquireRelease = 6,
+    SequentiallyConsistent = 7,
+}
+
+/// LLVMRustSynchronizationScope
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum SynchronizationScope {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    SingleThread,
+    CrossThread,
+}
+
+/// LLVMRustFileType
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum FileType {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    AssemblyFile,
+    ObjectFile,
+}
+
+/// LLVMMetadataType
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum MetadataType {
+    MD_dbg = 0,
+    MD_tbaa = 1,
+    MD_prof = 2,
+    MD_fpmath = 3,
+    MD_range = 4,
+    MD_tbaa_struct = 5,
+    MD_invariant_load = 6,
+    MD_alias_scope = 7,
+    MD_noalias = 8,
+    MD_nontemporal = 9,
+    MD_mem_parallel_loop_access = 10,
+    MD_nonnull = 11,
+}
+
+/// LLVMRustAsmDialect
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum AsmDialect {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    Att,
+    Intel,
+}
+
+/// LLVMRustCodeGenOptLevel
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CodeGenOptLevel {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    None,
+    Less,
+    Default,
+    Aggressive,
+}
+
+/// LLVMRelocMode
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum RelocMode {
+    Default,
+    Static,
+    PIC,
+    DynamicNoPic,
+    ROPI,
+    RWPI,
+    ROPI_RWPI,
+}
+
+/// LLVMRustCodeModel
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum CodeModel {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    Small,
+    Kernel,
+    Medium,
+    Large,
+    None,
+}
+
+/// LLVMRustDiagnosticKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[allow(dead_code)] // Variants constructed by C++.
+pub enum DiagnosticKind {
+    Other,
+    InlineAsm,
+    StackSize,
+    DebugMetadataVersion,
+    SampleProfile,
+    OptimizationRemark,
+    OptimizationRemarkMissed,
+    OptimizationRemarkAnalysis,
+    OptimizationRemarkAnalysisFPCommute,
+    OptimizationRemarkAnalysisAliasing,
+    OptimizationRemarkOther,
+    OptimizationFailure,
+    PGOProfile,
+    Linker,
+}
+
+/// LLVMRustArchiveKind
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ArchiveKind {
+    // FIXME: figure out if this variant is needed at all.
+    #[allow(dead_code)]
+    Other,
+    K_GNU,
+    K_BSD,
+    K_COFF,
+}
+
+/// LLVMRustPassKind
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[repr(C)]
+#[allow(dead_code)] // Variants constructed by C++.
+pub enum PassKind {
+    Other,
+    Function,
+    Module,
+}
+
+/// LLVMRustThinLTOData
+extern { pub type ThinLTOData; }
+
+/// LLVMRustThinLTOBuffer
+extern { pub type ThinLTOBuffer; }
+
+/// LLVMRustThinLTOModule
+#[repr(C)]
+pub struct ThinLTOModule {
+    pub identifier: *const c_char,
+    pub data: *const u8,
+    pub len: usize,
+}
+
+/// LLVMThreadLocalMode
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ThreadLocalMode {
+  NotThreadLocal,
+  GeneralDynamic,
+  LocalDynamic,
+  InitialExec,
+  LocalExec
+}
+
+extern { type Opaque; }
+#[repr(C)]
+struct InvariantOpaque<'a> {
+    _marker: PhantomData<&'a mut &'a ()>,
+    _opaque: Opaque,
+}
+
+// Opaque pointer types
+extern { pub type Module; }
+extern { pub type Context; }
+extern { pub type Type; }
+extern { pub type Value; }
+extern { pub type Metadata; }
+extern { pub type BasicBlock; }
+#[repr(C)]
+pub struct Builder<'a>(InvariantOpaque<'a>);
+extern { pub type MemoryBuffer; }
+#[repr(C)]
+pub struct PassManager<'a>(InvariantOpaque<'a>);
+extern { pub type PassManagerBuilder; }
+extern { pub type ObjectFile; }
+#[repr(C)]
+pub struct SectionIterator<'a>(InvariantOpaque<'a>);
+extern { pub type Pass; }
+extern { pub type TargetMachine; }
+extern { pub type Archive; }
+#[repr(C)]
+pub struct ArchiveIterator<'a>(InvariantOpaque<'a>);
+#[repr(C)]
+pub struct ArchiveChild<'a>(InvariantOpaque<'a>);
+extern { pub type Twine; }
+extern { pub type DiagnosticInfo; }
+extern { pub type SMDiagnostic; }
+#[repr(C)]
+pub struct RustArchiveMember<'a>(InvariantOpaque<'a>);
+#[repr(C)]
+pub struct OperandBundleDef<'a>(InvariantOpaque<'a>);
+#[repr(C)]
+pub struct Linker<'a>(InvariantOpaque<'a>);
+
+pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
+pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
+
+
+pub mod debuginfo {
+    use super::{InvariantOpaque, Metadata};
+
+    #[repr(C)]
+    pub struct DIBuilder<'a>(InvariantOpaque<'a>);
+
+    pub type DIDescriptor = Metadata;
+    pub type DIScope = DIDescriptor;
+    pub type DIFile = DIScope;
+    pub type DILexicalBlock = DIScope;
+    pub type DISubprogram = DIScope;
+    pub type DINameSpace = DIScope;
+    pub type DIType = DIDescriptor;
+    pub type DIBasicType = DIType;
+    pub type DIDerivedType = DIType;
+    pub type DICompositeType = DIDerivedType;
+    pub type DIVariable = DIDescriptor;
+    pub type DIGlobalVariable = DIDescriptor;
+    pub type DIArray = DIDescriptor;
+    pub type DISubrange = DIDescriptor;
+    pub type DIEnumerator = DIDescriptor;
+    pub type DITemplateTypeParameter = DIDescriptor;
+
+    // These values **must** match with LLVMRustDIFlags!!
+    bitflags! {
+        #[repr(C)]
+        #[derive(Default)]
+        pub struct DIFlags: ::libc::uint32_t {
+            const FlagZero                = 0;
+            const FlagPrivate             = 1;
+            const FlagProtected           = 2;
+            const FlagPublic              = 3;
+            const FlagFwdDecl             = (1 << 2);
+            const FlagAppleBlock          = (1 << 3);
+            const FlagBlockByrefStruct    = (1 << 4);
+            const FlagVirtual             = (1 << 5);
+            const FlagArtificial          = (1 << 6);
+            const FlagExplicit            = (1 << 7);
+            const FlagPrototyped          = (1 << 8);
+            const FlagObjcClassComplete   = (1 << 9);
+            const FlagObjectPointer       = (1 << 10);
+            const FlagVector              = (1 << 11);
+            const FlagStaticMember        = (1 << 12);
+            const FlagLValueReference     = (1 << 13);
+            const FlagRValueReference     = (1 << 14);
+            const FlagExternalTypeRef     = (1 << 15);
+            const FlagIntroducedVirtual   = (1 << 18);
+            const FlagBitField            = (1 << 19);
+            const FlagNoReturn            = (1 << 20);
+            const FlagMainSubprogram      = (1 << 21);
+        }
+    }
+}
+
+extern { pub type ModuleBuffer; }
+
+extern "C" {
+    // Create and destroy contexts.
+    pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;
+    pub fn LLVMContextDispose(C: &'static mut Context);
+    pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint;
+
+    // Create modules.
+    pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: &Context) -> &Module;
+    pub fn LLVMGetModuleContext(M: &Module) -> &Context;
+    pub fn LLVMCloneModule(M: &Module) -> &Module;
+
+    /// Data layout. See Module::getDataLayout.
+    pub fn LLVMGetDataLayout(M: &Module) -> *const c_char;
+    pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
+
+    /// See Module::setModuleInlineAsm.
+    pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char);
+    pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char);
+
+    /// See llvm::LLVMTypeKind::getTypeID.
+    pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
+
+    // Operations on integer types
+    pub fn LLVMInt1TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt8TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt16TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt32TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMInt64TypeInContext(C: &Context) -> &Type;
+    pub fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type;
+
+    pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint;
+
+    // Operations on real types
+    pub fn LLVMFloatTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
+
+    // Operations on function types
+    pub fn LLVMFunctionType(ReturnType: &'a Type,
+                            ParamTypes: *const &'a Type,
+                            ParamCount: c_uint,
+                            IsVarArg: Bool)
+                            -> &'a Type;
+    pub fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint;
+    pub fn LLVMGetParamTypes(FunctionTy: &'a Type, Dest: *mut &'a Type);
+
+    // Operations on struct types
+    pub fn LLVMStructTypeInContext(C: &'a Context,
+                                   ElementTypes: *const &'a Type,
+                                   ElementCount: c_uint,
+                                   Packed: Bool)
+                                   -> &'a Type;
+
+    // Operations on array, pointer, and vector types (sequence types)
+    pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type;
+    pub fn LLVMPointerType(ElementType: &Type, AddressSpace: c_uint) -> &Type;
+    pub fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
+
+    pub fn LLVMGetElementType(Ty: &Type) -> &Type;
+    pub fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint;
+
+    // Operations on other types
+    pub fn LLVMVoidTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMX86MMXTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type;
+
+    // Operations on all values
+    pub fn LLVMTypeOf(Val: &Value) -> &Type;
+    pub fn LLVMGetValueName(Val: &Value) -> *const c_char;
+    pub fn LLVMSetValueName(Val: &Value, Name: *const c_char);
+    pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value);
+    pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value);
+
+    // Operations on constants of any type
+    pub fn LLVMConstNull(Ty: &Type) -> &Value;
+    pub fn LLVMGetUndef(Ty: &Type) -> &Value;
+
+    // Operations on metadata
+    pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value;
+    pub fn LLVMMDNodeInContext(C: &'a Context, Vals: *const &'a Value, Count: c_uint) -> &'a Value;
+    pub fn LLVMAddNamedMetadataOperand(M: &'a Module, Name: *const c_char, Val: &'a Value);
+
+    // Operations on scalar constants
+    pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
+    pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value;
+    pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong;
+    pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool,
+                                  high: &mut u64, low: &mut u64) -> bool;
+    pub fn LLVMConstRealGetDouble (ConstantVal: &Value, losesInfo: &mut Bool) -> f64;
+
+
+    // Operations on composite constants
+    pub fn LLVMConstStringInContext(C: &Context,
+                                    Str: *const c_char,
+                                    Length: c_uint,
+                                    DontNullTerminate: Bool)
+                                    -> &Value;
+    pub fn LLVMConstStructInContext(C: &'a Context,
+                                    ConstantVals: *const &'a Value,
+                                    Count: c_uint,
+                                    Packed: Bool)
+                                    -> &'a Value;
+
+    pub fn LLVMConstArray(ElementTy: &'a Type,
+                          ConstantVals: *const &'a Value,
+                          Length: c_uint)
+                          -> &'a Value;
+    pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value;
+
+    // Constant expressions
+    pub fn LLVMConstInBoundsGEP(
+        ConstantVal: &'a Value,
+        ConstantIndices: *const &'a Value,
+        NumIndices: c_uint,
+    ) -> &'a Value;
+    pub fn LLVMConstZExt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstPtrToInt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstIntToPtr(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstBitCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstPointerCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+    pub fn LLVMConstExtractValue(AggConstant: &Value,
+                                 IdxList: *const c_uint,
+                                 NumIdx: c_uint)
+                                 -> &Value;
+
+    // Operations on global variables, functions, and aliases (globals)
+    pub fn LLVMIsDeclaration(Global: &Value) -> Bool;
+    pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage;
+    pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage);
+    pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
+    pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility;
+    pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility);
+    pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
+    pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
+    pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
+
+
+    // Operations on global variables
+    pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
+    pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
+    pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value;
+    pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
+    pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
+    pub fn LLVMDeleteGlobal(GlobalVar: &Value);
+    pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
+    pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value);
+    pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool);
+    pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
+    pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
+    pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
+    pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
+
+    // Operations on functions
+    pub fn LLVMRustGetOrInsertFunction(M: &'a Module,
+                                       Name: *const c_char,
+                                       FunctionTy: &'a Type)
+                                       -> &'a Value;
+    pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
+    pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
+    pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
+    pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
+                                              index: c_uint,
+                                              Name: *const c_char,
+                                              Value: *const c_char);
+    pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute);
+
+    // Operations on parameters
+    pub fn LLVMCountParams(Fn: &Value) -> c_uint;
+    pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value;
+
+    // Operations on basic blocks
+    pub fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value;
+    pub fn LLVMAppendBasicBlockInContext(C: &'a Context,
+                                         Fn: &'a Value,
+                                         Name: *const c_char)
+                                         -> &'a BasicBlock;
+    pub fn LLVMDeleteBasicBlock(BB: &BasicBlock);
+
+    // Operations on instructions
+    pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
+
+    // Operations on call sites
+    pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
+    pub fn LLVMRustAddCallSiteAttribute(Instr: &Value, index: c_uint, attr: Attribute);
+    pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: &Value, index: c_uint, bytes: u32);
+    pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
+                                                        index: c_uint,
+                                                        bytes: u64);
+
+    // Operations on load/store instructions (only)
+    pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
+
+    // Operations on phi nodes
+    pub fn LLVMAddIncoming(PhiNode: &'a Value,
+                           IncomingValues: *const &'a Value,
+                           IncomingBlocks: *const &'a BasicBlock,
+                           Count: c_uint);
+
+    // Instruction builders
+    pub fn LLVMCreateBuilderInContext(C: &'a Context) -> &'a mut Builder<'a>;
+    pub fn LLVMPositionBuilderAtEnd(Builder: &Builder<'a>, Block: &'a BasicBlock);
+    pub fn LLVMGetInsertBlock(Builder: &Builder<'a>) -> &'a BasicBlock;
+    pub fn LLVMDisposeBuilder(Builder: &'a mut Builder<'a>);
+
+    // Metadata
+    pub fn LLVMSetCurrentDebugLocation(Builder: &Builder<'a>, L: Option<&'a Value>);
+    pub fn LLVMGetCurrentDebugLocation(Builder: &Builder<'a>) -> &'a Value;
+    pub fn LLVMSetInstDebugLocation(Builder: &Builder<'a>, Inst: &'a Value);
+
+    // Terminators
+    pub fn LLVMBuildRetVoid(B: &Builder<'a>) -> &'a Value;
+    pub fn LLVMBuildRet(B: &Builder<'a>, V: &'a Value) -> &'a Value;
+    pub fn LLVMBuildBr(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value;
+    pub fn LLVMBuildCondBr(B: &Builder<'a>,
+                           If: &'a Value,
+                           Then: &'a BasicBlock,
+                           Else: &'a BasicBlock)
+                           -> &'a Value;
+    pub fn LLVMBuildSwitch(B: &Builder<'a>,
+                           V: &'a Value,
+                           Else: &'a BasicBlock,
+                           NumCases: c_uint)
+                           -> &'a Value;
+    pub fn LLVMRustBuildInvoke(B: &Builder<'a>,
+                               Fn: &'a Value,
+                               Args: *const &'a Value,
+                               NumArgs: c_uint,
+                               Then: &'a BasicBlock,
+                               Catch: &'a BasicBlock,
+                               Bundle: Option<&OperandBundleDef<'a>>,
+                               Name: *const c_char)
+                               -> &'a Value;
+    pub fn LLVMBuildLandingPad(B: &Builder<'a>,
+                               Ty: &'a Type,
+                               PersFn: &'a Value,
+                               NumClauses: c_uint,
+                               Name: *const c_char)
+                               -> &'a Value;
+    pub fn LLVMBuildResume(B: &Builder<'a>, Exn: &'a Value) -> &'a Value;
+    pub fn LLVMBuildUnreachable(B: &Builder<'a>) -> &'a Value;
+
+    pub fn LLVMRustBuildCleanupPad(B: &Builder<'a>,
+                                   ParentPad: Option<&'a Value>,
+                                   ArgCnt: c_uint,
+                                   Args: *const &'a Value,
+                                   Name: *const c_char)
+                                   -> Option<&'a Value>;
+    pub fn LLVMRustBuildCleanupRet(B: &Builder<'a>,
+                                   CleanupPad: &'a Value,
+                                   UnwindBB: Option<&'a BasicBlock>)
+                                   -> Option<&'a Value>;
+    pub fn LLVMRustBuildCatchPad(B: &Builder<'a>,
+                                 ParentPad: &'a Value,
+                                 ArgCnt: c_uint,
+                                 Args: *const &'a Value,
+                                 Name: *const c_char)
+                                 -> Option<&'a Value>;
+    pub fn LLVMRustBuildCatchRet(
+        B: &Builder<'a>,
+        Pad: &'a Value,
+        BB: &'a BasicBlock,
+    ) -> Option<&'a Value>;
+    pub fn LLVMRustBuildCatchSwitch(Builder: &Builder<'a>,
+                                    ParentPad: Option<&'a Value>,
+                                    BB: Option<&'a BasicBlock>,
+                                    NumHandlers: c_uint,
+                                    Name: *const c_char)
+                                    -> Option<&'a Value>;
+    pub fn LLVMRustAddHandler(CatchSwitch: &'a Value, Handler: &'a BasicBlock);
+    pub fn LLVMSetPersonalityFn(Func: &'a Value, Pers: &'a Value);
+
+    // Add a case to the switch instruction
+    pub fn LLVMAddCase(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock);
+
+    // Add a clause to the landing pad instruction
+    pub fn LLVMAddClause(LandingPad: &'a Value, ClauseVal: &'a Value);
+
+    // Set the cleanup on a landing pad instruction
+    pub fn LLVMSetCleanup(LandingPad: &Value, Val: Bool);
+
+    // Arithmetic
+    pub fn LLVMBuildAdd(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildFAdd(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildSub(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildFSub(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildMul(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildFMul(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildUDiv(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildExactUDiv(B: &Builder<'a>,
+                              LHS: &'a Value,
+                              RHS: &'a Value,
+                              Name: *const c_char)
+                              -> &'a Value;
+    pub fn LLVMBuildSDiv(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildExactSDiv(B: &Builder<'a>,
+                              LHS: &'a Value,
+                              RHS: &'a Value,
+                              Name: *const c_char)
+                              -> &'a Value;
+    pub fn LLVMBuildFDiv(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildURem(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildSRem(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildFRem(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildShl(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildLShr(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildAShr(B: &Builder<'a>,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildAnd(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildOr(B: &Builder<'a>,
+                       LHS: &'a Value,
+                       RHS: &'a Value,
+                       Name: *const c_char)
+                       -> &'a Value;
+    pub fn LLVMBuildXor(B: &Builder<'a>,
+                        LHS: &'a Value,
+                        RHS: &'a Value,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+    pub fn LLVMBuildFNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+    pub fn LLVMBuildNot(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+    pub fn LLVMRustSetHasUnsafeAlgebra(Instr: &Value);
+
+    // Memory
+    pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
+    pub fn LLVMBuildLoad(B: &Builder<'a>, PointerVal: &'a Value, Name: *const c_char) -> &'a Value;
+
+    pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
+
+    pub fn LLVMBuildGEP(B: &Builder<'a>,
+                        Pointer: &'a Value,
+                        Indices: *const &'a Value,
+                        NumIndices: c_uint,
+                        Name: *const c_char)
+                        -> &'a Value;
+    pub fn LLVMBuildInBoundsGEP(B: &Builder<'a>,
+                                Pointer: &'a Value,
+                                Indices: *const &'a Value,
+                                NumIndices: c_uint,
+                                Name: *const c_char)
+                                -> &'a Value;
+    pub fn LLVMBuildStructGEP(B: &Builder<'a>,
+                              Pointer: &'a Value,
+                              Idx: c_uint,
+                              Name: *const c_char)
+                              -> &'a Value;
+
+    // Casts
+    pub fn LLVMBuildTrunc(B: &Builder<'a>,
+                          Val: &'a Value,
+                          DestTy: &'a Type,
+                          Name: *const c_char)
+                          -> &'a Value;
+    pub fn LLVMBuildZExt(B: &Builder<'a>,
+                         Val: &'a Value,
+                         DestTy: &'a Type,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildSExt(B: &Builder<'a>,
+                         Val: &'a Value,
+                         DestTy: &'a Type,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildFPToUI(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildFPToSI(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildUIToFP(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildSIToFP(B: &Builder<'a>,
+                           Val: &'a Value,
+                           DestTy: &'a Type,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildFPTrunc(B: &Builder<'a>,
+                            Val: &'a Value,
+                            DestTy: &'a Type,
+                            Name: *const c_char)
+                            -> &'a Value;
+    pub fn LLVMBuildFPExt(B: &Builder<'a>,
+                          Val: &'a Value,
+                          DestTy: &'a Type,
+                          Name: *const c_char)
+                          -> &'a Value;
+    pub fn LLVMBuildPtrToInt(B: &Builder<'a>,
+                             Val: &'a Value,
+                             DestTy: &'a Type,
+                             Name: *const c_char)
+                             -> &'a Value;
+    pub fn LLVMBuildIntToPtr(B: &Builder<'a>,
+                             Val: &'a Value,
+                             DestTy: &'a Type,
+                             Name: *const c_char)
+                             -> &'a Value;
+    pub fn LLVMBuildBitCast(B: &Builder<'a>,
+                            Val: &'a Value,
+                            DestTy: &'a Type,
+                            Name: *const c_char)
+                            -> &'a Value;
+    pub fn LLVMBuildPointerCast(B: &Builder<'a>,
+                                Val: &'a Value,
+                                DestTy: &'a Type,
+                                Name: *const c_char)
+                                -> &'a Value;
+    pub fn LLVMRustBuildIntCast(B: &Builder<'a>,
+                                Val: &'a Value,
+                                DestTy: &'a Type,
+                                IsSized: bool)
+                                -> &'a Value;
+
+    // Comparisons
+    pub fn LLVMBuildICmp(B: &Builder<'a>,
+                         Op: c_uint,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+    pub fn LLVMBuildFCmp(B: &Builder<'a>,
+                         Op: c_uint,
+                         LHS: &'a Value,
+                         RHS: &'a Value,
+                         Name: *const c_char)
+                         -> &'a Value;
+
+    // Miscellaneous instructions
+    pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
+    pub fn LLVMRustBuildCall(B: &Builder<'a>,
+                             Fn: &'a Value,
+                             Args: *const &'a Value,
+                             NumArgs: c_uint,
+                             Bundle: Option<&OperandBundleDef<'a>>,
+                             Name: *const c_char)
+                             -> &'a Value;
+    pub fn LLVMBuildSelect(B: &Builder<'a>,
+                           If: &'a Value,
+                           Then: &'a Value,
+                           Else: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildVAArg(B: &Builder<'a>,
+                          list: &'a Value,
+                          Ty: &'a Type,
+                          Name: *const c_char)
+                          -> &'a Value;
+    pub fn LLVMBuildExtractElement(B: &Builder<'a>,
+                                   VecVal: &'a Value,
+                                   Index: &'a Value,
+                                   Name: *const c_char)
+                                   -> &'a Value;
+    pub fn LLVMBuildInsertElement(B: &Builder<'a>,
+                                  VecVal: &'a Value,
+                                  EltVal: &'a Value,
+                                  Index: &'a Value,
+                                  Name: *const c_char)
+                                  -> &'a Value;
+    pub fn LLVMBuildShuffleVector(B: &Builder<'a>,
+                                  V1: &'a Value,
+                                  V2: &'a Value,
+                                  Mask: &'a Value,
+                                  Name: *const c_char)
+                                  -> &'a Value;
+    pub fn LLVMBuildExtractValue(B: &Builder<'a>,
+                                 AggVal: &'a Value,
+                                 Index: c_uint,
+                                 Name: *const c_char)
+                                 -> &'a Value;
+    pub fn LLVMBuildInsertValue(B: &Builder<'a>,
+                                AggVal: &'a Value,
+                                EltVal: &'a Value,
+                                Index: c_uint,
+                                Name: *const c_char)
+                                -> &'a Value;
+
+    pub fn LLVMRustBuildVectorReduceFAdd(B: &Builder<'a>,
+                                         Acc: &'a Value,
+                                         Src: &'a Value)
+                                         -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceFMul(B: &Builder<'a>,
+                                         Acc: &'a Value,
+                                         Src: &'a Value)
+                                         -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceAdd(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceMul(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceAnd(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceOr(B: &Builder<'a>,
+                                       Src: &'a Value)
+                                       -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceXor(B: &Builder<'a>,
+                                        Src: &'a Value)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceMin(B: &Builder<'a>,
+                                        Src: &'a Value,
+                                        IsSigned: bool)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceMax(B: &Builder<'a>,
+                                        Src: &'a Value,
+                                        IsSigned: bool)
+                                        -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceFMin(B: &Builder<'a>,
+                                         Src: &'a Value,
+                                         IsNaN: bool)
+                                         -> Option<&'a Value>;
+    pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>,
+                                         Src: &'a Value,
+                                         IsNaN: bool)
+                                         -> Option<&'a Value>;
+
+    pub fn LLVMRustBuildMinNum(
+        B: &Builder<'a>,
+        LHS: &'a Value,
+        LHS: &'a Value,
+    ) -> Option<&'a Value>;
+    pub fn LLVMRustBuildMaxNum(
+        B: &Builder<'a>,
+        LHS: &'a Value,
+        LHS: &'a Value,
+    ) -> Option<&'a Value>;
+
+    // Atomic Operations
+    pub fn LLVMRustBuildAtomicLoad(B: &Builder<'a>,
+                                   PointerVal: &'a Value,
+                                   Name: *const c_char,
+                                   Order: AtomicOrdering)
+                                   -> &'a Value;
+
+    pub fn LLVMRustBuildAtomicStore(B: &Builder<'a>,
+                                    Val: &'a Value,
+                                    Ptr: &'a Value,
+                                    Order: AtomicOrdering)
+                                    -> &'a Value;
+
+    pub fn LLVMRustBuildAtomicCmpXchg(B: &Builder<'a>,
+                                      LHS: &'a Value,
+                                      CMP: &'a Value,
+                                      RHS: &'a Value,
+                                      Order: AtomicOrdering,
+                                      FailureOrder: AtomicOrdering,
+                                      Weak: Bool)
+                                      -> &'a Value;
+
+    pub fn LLVMBuildAtomicRMW(B: &Builder<'a>,
+                              Op: AtomicRmwBinOp,
+                              LHS: &'a Value,
+                              RHS: &'a Value,
+                              Order: AtomicOrdering,
+                              SingleThreaded: Bool)
+                              -> &'a Value;
+
+    pub fn LLVMRustBuildAtomicFence(B: &Builder,
+                                    Order: AtomicOrdering,
+                                    Scope: SynchronizationScope);
+
+    /// Writes a module to the specified path. Returns 0 on success.
+    pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
+
+    /// Creates a pass manager.
+    pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>;
+
+    /// Creates a function-by-function pass manager
+    pub fn LLVMCreateFunctionPassManagerForModule(M: &'a Module) -> &'a mut PassManager<'a>;
+
+    /// Disposes a pass manager.
+    pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>);
+
+    /// Runs a pass manager on a module.
+    pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool;
+
+    pub fn LLVMInitializePasses();
+
+    pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;
+    pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder);
+    pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: &PassManagerBuilder, Value: Bool);
+    pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: &PassManagerBuilder, Value: Bool);
+    pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: &PassManagerBuilder,
+                                                         threshold: c_uint);
+    pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: &PassManagerBuilder,
+                                                           PM: &PassManager);
+
+    pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: &PassManagerBuilder,
+                                                             PM: &PassManager);
+    pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder,
+                                                        PM: &PassManager,
+                                                        Internalize: Bool,
+                                                        RunInliner: Bool);
+    pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
+        PMB: &PassManagerBuilder,
+        PM: &PassManager) -> bool;
+
+    // Stuff that's in rustllvm/ because it's not upstream yet.
+
+    /// Opens an object file.
+    pub fn LLVMCreateObjectFile(
+        MemBuf: &'static mut MemoryBuffer,
+    ) -> Option<&'static mut ObjectFile>;
+    /// Closes an object file.
+    pub fn LLVMDisposeObjectFile(ObjFile: &'static mut ObjectFile);
+
+    /// Enumerates the sections in an object file.
+    pub fn LLVMGetSections(ObjFile: &'a ObjectFile) -> &'a mut SectionIterator<'a>;
+    /// Destroys a section iterator.
+    pub fn LLVMDisposeSectionIterator(SI: &'a mut SectionIterator<'a>);
+    /// Returns true if the section iterator is at the end of the section
+    /// list:
+    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: &'a ObjectFile, SI: &SectionIterator<'a>) -> Bool;
+    /// Moves the section iterator to point to the next section.
+    pub fn LLVMMoveToNextSection(SI: &SectionIterator);
+    /// Returns the current section size.
+    pub fn LLVMGetSectionSize(SI: &SectionIterator) -> c_ulonglong;
+    /// Returns the current section contents as a string buffer.
+    pub fn LLVMGetSectionContents(SI: &SectionIterator) -> *const c_char;
+
+    /// Reads the given file and returns it as a memory buffer. Use
+    /// LLVMDisposeMemoryBuffer() to get rid of it.
+    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(
+        Path: *const c_char,
+    ) -> Option<&'static mut MemoryBuffer>;
+
+    pub fn LLVMStartMultithreaded() -> Bool;
+
+    /// Returns a string describing the last error caused by an LLVMRust* call.
+    pub fn LLVMRustGetLastError() -> *const c_char;
+
+    /// Print the pass timings since static dtors aren't picking them up.
+    pub fn LLVMRustPrintPassTimings();
+
+    pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type;
+
+    pub fn LLVMStructSetBody(StructTy: &'a Type,
+                             ElementTypes: *const &'a Type,
+                             ElementCount: c_uint,
+                             Packed: Bool);
+
+    /// Prepares inline assembly.
+    pub fn LLVMRustInlineAsm(Ty: &Type,
+                             AsmString: *const c_char,
+                             Constraints: *const c_char,
+                             SideEffects: Bool,
+                             AlignStack: Bool,
+                             Dialect: AsmDialect)
+                             -> &Value;
+
+    pub fn LLVMRustDebugMetadataVersion() -> u32;
+    pub fn LLVMRustVersionMajor() -> u32;
+    pub fn LLVMRustVersionMinor() -> u32;
+
+    pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
+
+    pub fn LLVMRustMetadataAsValue(C: &'a Context, MD: &'a Metadata) -> &'a Value;
+
+    pub fn LLVMRustDIBuilderCreate(M: &'a Module) -> &'a mut DIBuilder<'a>;
+
+    pub fn LLVMRustDIBuilderDispose(Builder: &'a mut DIBuilder<'a>);
+
+    pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder);
+
+    pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: &DIBuilder<'a>,
+                                              Lang: c_uint,
+                                              File: &'a DIFile,
+                                              Producer: *const c_char,
+                                              isOptimized: bool,
+                                              Flags: *const c_char,
+                                              RuntimeVer: c_uint,
+                                              SplitName: *const c_char)
+                                              -> &'a DIDescriptor;
+
+    pub fn LLVMRustDIBuilderCreateFile(Builder: &DIBuilder<'a>,
+                                       Filename: *const c_char,
+                                       Directory: *const c_char)
+                                       -> &'a DIFile;
+
+    pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: &DIBuilder<'a>,
+                                                 File: &'a DIFile,
+                                                 ParameterTypes: &'a DIArray)
+                                                 -> &'a DICompositeType;
+
+    pub fn LLVMRustDIBuilderCreateFunction(Builder: &DIBuilder<'a>,
+                                           Scope: &'a DIDescriptor,
+                                           Name: *const c_char,
+                                           LinkageName: *const c_char,
+                                           File: &'a DIFile,
+                                           LineNo: c_uint,
+                                           Ty: &'a DIType,
+                                           isLocalToUnit: bool,
+                                           isDefinition: bool,
+                                           ScopeLine: c_uint,
+                                           Flags: DIFlags,
+                                           isOptimized: bool,
+                                           Fn: &'a Value,
+                                           TParam: &'a DIArray,
+                                           Decl: Option<&'a DIDescriptor>)
+                                           -> &'a DISubprogram;
+
+    pub fn LLVMRustDIBuilderCreateBasicType(Builder: &DIBuilder<'a>,
+                                            Name: *const c_char,
+                                            SizeInBits: u64,
+                                            AlignInBits: u32,
+                                            Encoding: c_uint)
+                                            -> &'a DIBasicType;
+
+    pub fn LLVMRustDIBuilderCreatePointerType(Builder: &DIBuilder<'a>,
+                                              PointeeTy: &'a DIType,
+                                              SizeInBits: u64,
+                                              AlignInBits: u32,
+                                              Name: *const c_char)
+                                              -> &'a DIDerivedType;
+
+    pub fn LLVMRustDIBuilderCreateStructType(Builder: &DIBuilder<'a>,
+                                             Scope: Option<&'a DIDescriptor>,
+                                             Name: *const c_char,
+                                             File: &'a DIFile,
+                                             LineNumber: c_uint,
+                                             SizeInBits: u64,
+                                             AlignInBits: u32,
+                                             Flags: DIFlags,
+                                             DerivedFrom: Option<&'a DIType>,
+                                             Elements: &'a DIArray,
+                                             RunTimeLang: c_uint,
+                                             VTableHolder: Option<&'a DIType>,
+                                             UniqueId: *const c_char)
+                                             -> &'a DICompositeType;
+
+    pub fn LLVMRustDIBuilderCreateMemberType(Builder: &DIBuilder<'a>,
+                                             Scope: &'a DIDescriptor,
+                                             Name: *const c_char,
+                                             File: &'a DIFile,
+                                             LineNo: c_uint,
+                                             SizeInBits: u64,
+                                             AlignInBits: u32,
+                                             OffsetInBits: u64,
+                                             Flags: DIFlags,
+                                             Ty: &'a DIType)
+                                             -> &'a DIDerivedType;
+
+    pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: &DIBuilder<'a>,
+                                               Scope: &'a DIScope,
+                                               File: &'a DIFile,
+                                               Line: c_uint,
+                                               Col: c_uint)
+                                               -> &'a DILexicalBlock;
+
+    pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: &DIBuilder<'a>,
+                                                   Scope: &'a DIScope,
+                                                   File: &'a DIFile)
+                                                   -> &'a DILexicalBlock;
+
+    pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: &DIBuilder<'a>,
+                                                 Context: Option<&'a DIScope>,
+                                                 Name: *const c_char,
+                                                 LinkageName: *const c_char,
+                                                 File: &'a DIFile,
+                                                 LineNo: c_uint,
+                                                 Ty: &'a DIType,
+                                                 isLocalToUnit: bool,
+                                                 Val: &'a Value,
+                                                 Decl: Option<&'a DIDescriptor>,
+                                                 AlignInBits: u32)
+                                                 -> &'a DIGlobalVariable;
+
+    pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>,
+                                           Tag: c_uint,
+                                           Scope: &'a DIDescriptor,
+                                           Name: *const c_char,
+                                           File: &'a DIFile,
+                                           LineNo: c_uint,
+                                           Ty: &'a DIType,
+                                           AlwaysPreserve: bool,
+                                           Flags: DIFlags,
+                                           ArgNo: c_uint,
+                                           AlignInBits: u32)
+                                           -> &'a DIVariable;
+
+    pub fn LLVMRustDIBuilderCreateArrayType(Builder: &DIBuilder<'a>,
+                                            Size: u64,
+                                            AlignInBits: u32,
+                                            Ty: &'a DIType,
+                                            Subscripts: &'a DIArray)
+                                            -> &'a DIType;
+
+    pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: &DIBuilder<'a>,
+                                                Lo: i64,
+                                                Count: i64)
+                                                -> &'a DISubrange;
+
+    pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: &DIBuilder<'a>,
+                                             Ptr: *const Option<&'a DIDescriptor>,
+                                             Count: c_uint)
+                                             -> &'a DIArray;
+
+    pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: &DIBuilder<'a>,
+                                               Val: &'a Value,
+                                               VarInfo: &'a DIVariable,
+                                               AddrOps: *const i64,
+                                               AddrOpsCount: c_uint,
+                                               DL: &'a Value,
+                                               InsertAtEnd: &'a BasicBlock)
+                                               -> &'a Value;
+
+    pub fn LLVMRustDIBuilderCreateEnumerator(Builder: &DIBuilder<'a>,
+                                             Name: *const c_char,
+                                             Val: u64)
+                                             -> &'a DIEnumerator;
+
+    pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: &DIBuilder<'a>,
+                                                  Scope: &'a DIScope,
+                                                  Name: *const c_char,
+                                                  File: &'a DIFile,
+                                                  LineNumber: c_uint,
+                                                  SizeInBits: u64,
+                                                  AlignInBits: u32,
+                                                  Elements: &'a DIArray,
+                                                  ClassType: &'a DIType)
+                                                  -> &'a DIType;
+
+    pub fn LLVMRustDIBuilderCreateUnionType(Builder: &DIBuilder<'a>,
+                                            Scope: &'a DIScope,
+                                            Name: *const c_char,
+                                            File: &'a DIFile,
+                                            LineNumber: c_uint,
+                                            SizeInBits: u64,
+                                            AlignInBits: u32,
+                                            Flags: DIFlags,
+                                            Elements: Option<&'a DIArray>,
+                                            RunTimeLang: c_uint,
+                                            UniqueId: *const c_char)
+                                            -> &'a DIType;
+
+    pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool);
+
+    pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: &DIBuilder<'a>,
+                                                        Scope: Option<&'a DIScope>,
+                                                        Name: *const c_char,
+                                                        Ty: &'a DIType,
+                                                        File: &'a DIFile,
+                                                        LineNo: c_uint,
+                                                        ColumnNo: c_uint)
+                                                        -> &'a DITemplateTypeParameter;
+
+
+    pub fn LLVMRustDIBuilderCreateNameSpace(Builder: &DIBuilder<'a>,
+                                            Scope: Option<&'a DIScope>,
+                                            Name: *const c_char,
+                                            File: &'a DIFile,
+                                            LineNo: c_uint)
+                                            -> &'a DINameSpace;
+
+    pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: &DIBuilder<'a>,
+                                               CompositeType: &'a DIType,
+                                               TypeArray: &'a DIArray);
+
+
+    pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context,
+                                                Line: c_uint,
+                                                Column: c_uint,
+                                                Scope: &'a DIScope,
+                                                InlinedAt: Option<&'a Metadata>)
+                                                -> &'a Value;
+    pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
+    pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
+    pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>;
+    pub fn LLVMIsAConstantFP(value_ref: &Value) -> Option<&Value>;
+
+    pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind;
+    pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>;
+    pub fn LLVMRustAddPass(PM: &PassManager, Pass: &'static mut Pass);
+
+    pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
+
+    pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine);
+    pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine);
+
+    pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
+                                       CPU: *const c_char,
+                                       Features: *const c_char,
+                                       Model: CodeModel,
+                                       Reloc: RelocMode,
+                                       Level: CodeGenOptLevel,
+                                       UseSoftFP: bool,
+                                       PositionIndependentExecutable: bool,
+                                       FunctionSections: bool,
+                                       DataSections: bool,
+                                       TrapUnreachable: bool,
+                                       Singlethread: bool)
+                                       -> Option<&'static mut TargetMachine>;
+    pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
+    pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module);
+    pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder,
+                                         M: &'a Module,
+                                         DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustConfigurePassManagerBuilder(PMB: &PassManagerBuilder,
+                                               OptLevel: CodeGenOptLevel,
+                                               MergeFunctions: bool,
+                                               SLPVectorize: bool,
+                                               LoopVectorize: bool,
+                                               PrepareForThinLTO: bool,
+                                               PGOGenPath: *const c_char,
+                                               PGOUsePath: *const c_char);
+    pub fn LLVMRustAddLibraryInfo(PM: &PassManager<'a>,
+                                  M: &'a Module,
+                                  DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module);
+    pub fn LLVMRustWriteOutputFile(T: &'a TargetMachine,
+                                   PM: &PassManager<'a>,
+                                   M: &'a Module,
+                                   Output: *const c_char,
+                                   FileType: FileType)
+                                   -> LLVMRustResult;
+    pub fn LLVMRustPrintModule(PM: &PassManager<'a>,
+                               M: &'a Module,
+                               Output: *const c_char,
+                               Demangle: extern fn(*const c_char,
+                                                   size_t,
+                                                   *mut c_char,
+                                                   size_t) -> size_t);
+    pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
+    pub fn LLVMRustPrintPasses();
+    pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
+    pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool);
+    pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
+    pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module);
+
+    pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>;
+    pub fn LLVMRustArchiveIteratorNew(AR: &'a Archive) -> &'a mut ArchiveIterator<'a>;
+    pub fn LLVMRustArchiveIteratorNext(
+        AIR: &ArchiveIterator<'a>,
+    ) -> Option<&'a mut ArchiveChild<'a>>;
+    pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char;
+    pub fn LLVMRustArchiveChildData(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char;
+    pub fn LLVMRustArchiveChildFree(ACR: &'a mut ArchiveChild<'a>);
+    pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>);
+    pub fn LLVMRustDestroyArchive(AR: &'static mut Archive);
+
+    pub fn LLVMRustGetSectionName(SI: &SectionIterator, data: &mut *const c_char) -> size_t;
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMContextSetDiagnosticHandler(C: &Context,
+                                           Handler: DiagnosticHandler,
+                                           DiagnosticContext: *mut c_void);
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustUnpackOptimizationDiagnostic(DI: &'a DiagnosticInfo,
+                                                pass_name_out: &RustString,
+                                                function_out: &mut Option<&'a Value>,
+                                                loc_line_out: &mut c_uint,
+                                                loc_column_out: &mut c_uint,
+                                                loc_filename_out: &RustString,
+                                                message_out: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: &'a DiagnosticInfo,
+                                             cookie_out: &mut c_uint,
+                                             message_out: &mut Option<&'a Twine>,
+                                             instruction_out: &mut Option<&'a Value>);
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
+
+    pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: &Context,
+                                                 H: InlineAsmDiagHandler,
+                                                 CX: *mut c_void);
+}
+
+#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString.
+extern "C" {
+    pub fn LLVMRustWriteSMDiagnosticToString(d: &SMDiagnostic, s: &RustString);
+}
+
+extern "C" {
+    pub fn LLVMRustWriteArchive(Dst: *const c_char,
+                                NumMembers: size_t,
+                                Members: *const &RustArchiveMember,
+                                WriteSymbtab: bool,
+                                Kind: ArchiveKind)
+                                -> LLVMRustResult;
+    pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
+                                    Name: *const c_char,
+                                    Child: Option<&'a ArchiveChild>)
+                                    -> &'a mut RustArchiveMember<'a>;
+    pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>);
+
+    pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine);
+
+    pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
+                                         Inputs: *const &'a Value,
+                                         NumInputs: c_uint)
+                                         -> &'a mut OperandBundleDef<'a>;
+    pub fn LLVMRustFreeOperandBundleDef(Bundle: &'a mut OperandBundleDef<'a>);
+
+    pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock);
+
+    pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char);
+    pub fn LLVMRustUnsetComdat(V: &Value);
+    pub fn LLVMRustSetModulePIELevel(M: &Module);
+    pub fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer;
+    pub fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8;
+    pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
+    pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
+    pub fn LLVMRustModuleCost(M: &Module) -> u64;
+
+    pub fn LLVMRustThinLTOAvailable() -> bool;
+    pub fn LLVMRustPGOAvailable() -> bool;
+    pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> &'static mut ThinLTOBuffer;
+    pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
+    pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
+    pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
+    pub fn LLVMRustCreateThinLTOData(
+        Modules: *const ThinLTOModule,
+        NumModules: c_uint,
+        PreservedSymbols: *const *const c_char,
+        PreservedSymbolsLen: c_uint,
+    ) -> Option<&'static mut ThinLTOData>;
+    pub fn LLVMRustPrepareThinLTORename(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustPrepareThinLTOResolveWeak(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustPrepareThinLTOInternalize(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustPrepareThinLTOImport(
+        Data: &ThinLTOData,
+        Module: &Module,
+    ) -> bool;
+    pub fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData);
+    pub fn LLVMRustParseBitcodeForThinLTO(
+        Context: &Context,
+        Data: *const u8,
+        len: usize,
+        Identifier: *const c_char,
+    ) -> Option<&Module>;
+    pub fn LLVMRustThinLTOGetDICompileUnit(M: &Module,
+                                           CU1: &mut *mut c_void,
+                                           CU2: &mut *mut c_void);
+    pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
+
+    pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>;
+    pub fn LLVMRustLinkerAdd(linker: &Linker,
+                             bytecode: *const c_char,
+                             bytecode_len: usize) -> bool;
+    pub fn LLVMRustLinkerFree(linker: &'a mut Linker<'a>);
+}
diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs
new file mode 100644 (file)
index 0000000..558d2a2
--- /dev/null
@@ -0,0 +1,281 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![deny(bare_trait_objects)]
+
+pub use self::IntPredicate::*;
+pub use self::RealPredicate::*;
+pub use self::AtomicRmwBinOp::*;
+pub use self::MetadataType::*;
+pub use self::CodeGenOptSize::*;
+pub use self::CallConv::*;
+pub use self::Linkage::*;
+
+use std::str::FromStr;
+use std::string::FromUtf8Error;
+use std::slice;
+use std::ffi::{CString, CStr};
+use std::cell::RefCell;
+use libc::{self, c_uint, c_char, size_t};
+
+pub mod archive_ro;
+pub mod diagnostic;
+mod ffi;
+
+pub use self::ffi::*;
+
+impl LLVMRustResult {
+    pub fn into_result(self) -> Result<(), ()> {
+        match self {
+            LLVMRustResult::Success => Ok(()),
+            LLVMRustResult::Failure => Err(()),
+        }
+    }
+}
+
+pub fn AddFunctionAttrStringValue(llfn: &'a Value,
+                                  idx: AttributePlace,
+                                  attr: &CStr,
+                                  value: &CStr) {
+    unsafe {
+        LLVMRustAddFunctionAttrStringValue(llfn,
+                                           idx.as_uint(),
+                                           attr.as_ptr(),
+                                           value.as_ptr())
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum AttributePlace {
+    ReturnValue,
+    Argument(u32),
+    Function,
+}
+
+impl AttributePlace {
+    pub fn as_uint(self) -> c_uint {
+        match self {
+            AttributePlace::ReturnValue => 0,
+            AttributePlace::Argument(i) => 1 + i,
+            AttributePlace::Function => !0,
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum CodeGenOptSize {
+    CodeGenOptSizeNone = 0,
+    CodeGenOptSizeDefault = 1,
+    CodeGenOptSizeAggressive = 2,
+}
+
+impl FromStr for ArchiveKind {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "gnu" => Ok(ArchiveKind::K_GNU),
+            "bsd" => Ok(ArchiveKind::K_BSD),
+            "coff" => Ok(ArchiveKind::K_COFF),
+            _ => Err(()),
+        }
+    }
+}
+
+#[repr(C)]
+pub struct RustString {
+    bytes: RefCell<Vec<u8>>,
+}
+
+/// Appending to a Rust string -- used by RawRustStringOstream.
+#[no_mangle]
+pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
+                                                 ptr: *const c_char,
+                                                 size: size_t) {
+    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
+
+    sr.bytes.borrow_mut().extend_from_slice(slice);
+}
+
+pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) {
+    unsafe {
+        LLVMSetInstructionCallConv(instr, cc as c_uint);
+    }
+}
+pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) {
+    unsafe {
+        LLVMSetFunctionCallConv(fn_, cc as c_uint);
+    }
+}
+
+// Externally visible symbols that might appear in multiple codegen units need to appear in
+// their own comdat section so that the duplicates can be discarded at link time. This can for
+// example happen for generics when using multiple codegen units. This function simply uses the
+// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
+// function.
+// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
+pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
+    unsafe {
+        LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
+    }
+}
+
+pub fn UnsetComdat(val: &'a Value) {
+    unsafe {
+        LLVMRustUnsetComdat(val);
+    }
+}
+
+pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) {
+    unsafe {
+        LLVMSetUnnamedAddr(global, unnamed as Bool);
+    }
+}
+
+pub fn set_thread_local(global: &'a Value, is_thread_local: bool) {
+    unsafe {
+        LLVMSetThreadLocal(global, is_thread_local as Bool);
+    }
+}
+pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) {
+    unsafe {
+        LLVMSetThreadLocalMode(global, mode);
+    }
+}
+
+impl Attribute {
+    pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
+        unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
+    }
+
+    pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
+        unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
+    }
+
+    pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) {
+        unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
+    }
+
+    pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) {
+        if set {
+            self.apply_llfn(idx, llfn);
+        } else {
+            self.unapply_llfn(idx, llfn);
+        }
+    }
+}
+
+// Memory-managed interface to object files.
+
+pub struct ObjectFile {
+    pub llof: &'static mut ffi::ObjectFile,
+}
+
+unsafe impl Send for ObjectFile {}
+
+impl ObjectFile {
+    // This will take ownership of llmb
+    pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
+        unsafe {
+            let llof = LLVMCreateObjectFile(llmb)?;
+            Some(ObjectFile { llof: llof })
+        }
+    }
+}
+
+impl Drop for ObjectFile {
+    fn drop(&mut self) {
+        unsafe {
+            LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
+        }
+    }
+}
+
+// Memory-managed interface to section iterators.
+
+pub struct SectionIter<'a> {
+    pub llsi: &'a mut SectionIterator<'a>,
+}
+
+impl Drop for SectionIter<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
+        }
+    }
+}
+
+pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
+    unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
+}
+
+/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
+pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
+    unsafe {
+        assert!(index < LLVMCountParams(llfn),
+            "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
+        LLVMGetParam(llfn, index)
+    }
+}
+
+pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
+    let sr = RustString {
+        bytes: RefCell::new(Vec::new()),
+    };
+    f(&sr);
+    String::from_utf8(sr.bytes.into_inner())
+}
+
+pub fn twine_to_string(tr: &Twine) -> String {
+    unsafe {
+        build_string(|s| LLVMRustWriteTwineToString(tr, s))
+            .expect("got a non-UTF8 Twine from LLVM")
+    }
+}
+
+pub fn last_error() -> Option<String> {
+    unsafe {
+        let cstr = LLVMRustGetLastError();
+        if cstr.is_null() {
+            None
+        } else {
+            let err = CStr::from_ptr(cstr).to_bytes();
+            let err = String::from_utf8_lossy(err).to_string();
+            libc::free(cstr as *mut _);
+            Some(err)
+        }
+    }
+}
+
+pub struct OperandBundleDef<'a> {
+    pub raw: &'a mut ffi::OperandBundleDef<'a>,
+}
+
+impl OperandBundleDef<'a> {
+    pub fn new(name: &str, vals: &[&'a Value]) -> Self {
+        let name = CString::new(name).unwrap();
+        let def = unsafe {
+            LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
+        };
+        OperandBundleDef { raw: def }
+    }
+}
+
+impl Drop for OperandBundleDef<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
+        }
+    }
+}
index e941998098d00ceba7242969c8579151a0915945..441fff5f08c8fddb258923616b2726fda2b00f5e 100644 (file)
@@ -73,7 +73,7 @@ unsafe fn configure_llvm(sess: &Session) {
 
     llvm::LLVMInitializePasses();
 
-    llvm::initialize_available_targets();
+    ::rustc_llvm::initialize_available_targets();
 
     llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                  llvm_args.as_ptr());
index 144baa65c1bfa32a6b19b29391799d5811de5f5d..fcb704413ef116c1944e486083f4a995dcbffaba 100644 (file)
@@ -58,10 +58,8 @@ fn get_dylib_metadata(&self,
                           -> Result<MetadataRef, String> {
         unsafe {
             let buf = common::path2cstr(filename);
-            let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
-            if mb as isize == 0 {
-                return Err(format!("error reading library: '{}'", filename.display()));
-            }
+            let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr())
+                .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?;
             let of = ObjectFile::new(mb)
                 .map(|of| OwningRef::new(box of))
                 .ok_or_else(|| format!("provided path not an object file: '{}'",
index 21bbdf31dcb5200d8fa04068ad3e94fa83fec9f1..9c0dd0dc3d8b54f54e5409c381c7cdeb3d68467e 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::ValueRef;
 use abi::{FnType, FnTypeExt};
 use callee;
 use common::*;
@@ -17,6 +16,7 @@
 use monomorphize;
 use type_::Type;
 use value::Value;
+
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::HasDataLayout;
 use debuginfo;
@@ -33,11 +33,11 @@ pub fn from_index(index: usize) -> Self {
         VirtualIndex(index as u64 + 3)
     }
 
-    pub fn get_fn(self, bx: &Builder<'a, 'tcx>,
-                  llvtable: ValueRef,
-                  fn_ty: &FnType<'tcx, Ty<'tcx>>) -> ValueRef {
+    pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>,
+                  llvtable: &'ll Value,
+                  fn_ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Value {
         // Load the data pointer from the object.
-        debug!("get_fn({:?}, {:?})", Value(llvtable), self);
+        debug!("get_fn({:?}, {:?})", llvtable, self);
 
         let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to());
         let ptr_align = bx.tcx().data_layout.pointer_align;
@@ -48,9 +48,9 @@ pub fn get_fn(self, bx: &Builder<'a, 'tcx>,
         ptr
     }
 
-    pub fn get_usize(self, bx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
+    pub fn get_usize(self, bx: &Builder<'a, 'll, 'tcx>, llvtable: &'ll Value) -> &'ll Value {
         // Load the data pointer from the object.
-        debug!("get_int({:?}, {:?})", Value(llvtable), self);
+        debug!("get_int({:?}, {:?})", llvtable, self);
 
         let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to());
         let usize_align = bx.tcx().data_layout.pointer_align;
@@ -69,11 +69,11 @@ pub fn get_usize(self, bx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef {
 /// The `trait_ref` encodes the erased self type. Hence if we are
 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
 /// `trait_ref` would map `T:Trait`.
-pub fn get_vtable<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                            ty: Ty<'tcx>,
-                            trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
-                            -> ValueRef
-{
+pub fn get_vtable(
+    cx: &CodegenCx<'ll, 'tcx>,
+    ty: Ty<'tcx>,
+    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+) -> &'ll Value {
     let tcx = cx.tcx;
 
     debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
index e105baba8aa2e56f441123600b506068d28dc519..993138aee1cec90e9560c9a5859baec62c96f3bf 100644 (file)
@@ -11,7 +11,7 @@
 //! An analysis to determine which locals require allocas and
 //! which do not.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::mir::{self, Location, TerminatorKind};
@@ -22,7 +22,7 @@
 use type_of::LayoutLlvmExt;
 use super::FunctionCx;
 
-pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector<mir::Local> {
+pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray<mir::Local> {
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
@@ -34,7 +34,7 @@ pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector<mir::Loc
         let layout = fx.cx.layout_of(ty);
         if layout.is_llvm_immediate() {
             // These sorts of types are immediates that we can store
-            // in an ValueRef without an alloca.
+            // in an Value without an alloca.
         } else if layout.is_llvm_scalar_pair() {
             // We allow pairs and uses of any of their 2 fields.
         } else {
@@ -51,23 +51,23 @@ pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector<mir::Loc
     analyzer.non_ssa_locals
 }
 
-struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
-    fx: &'mir FunctionCx<'a, 'tcx>,
+struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> {
+    fx: &'mir FunctionCx<'a, 'll, 'tcx>,
     dominators: Dominators<mir::BasicBlock>,
-    non_ssa_locals: BitVector<mir::Local>,
+    non_ssa_locals: BitArray<mir::Local>,
     // The location of the first visited direct assignment to each
     // local, or an invalid location (out of bounds `block` index).
     first_assignment: IndexVec<mir::Local, Location>
 }
 
-impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
-    fn new(fx: &'mir FunctionCx<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> {
+impl LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
+    fn new(fx: &'mir FunctionCx<'a, 'll, 'tcx>) -> Self {
         let invalid_location =
             mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
         let mut analyzer = LocalAnalyzer {
             fx,
             dominators: fx.mir.dominators(),
-            non_ssa_locals: BitVector::new(fx.mir.local_decls.len()),
+            non_ssa_locals: BitArray::new(fx.mir.local_decls.len()),
             first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls)
         };
 
@@ -102,7 +102,7 @@ fn assign(&mut self, local: mir::Local, location: Location) {
     }
 }
 
-impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
+impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
     fn visit_assign(&mut self,
                     block: mir::BasicBlock,
                     place: &mir::Place<'tcx>,
index dc4b9e0ae99d8f41a83b0fb044d43e891e1aca82..684ecfaeec8f159d858f736e22b2d45b6a6699cd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef, BasicBlockRef};
+use llvm::{self, BasicBlock};
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf};
@@ -24,6 +24,7 @@
 use monomorphize;
 use type_of::LayoutLlvmExt;
 use type_::Type;
+use value::Value;
 
 use syntax::symbol::Symbol;
 use syntax_pos::Pos;
@@ -33,7 +34,7 @@
 use super::operand::OperandRef;
 use super::operand::OperandValue::{Pair, Ref, Immediate};
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_block(&mut self, bb: mir::BasicBlock) {
         let mut bx = self.build_block(bb);
         let data = &self.mir[bb];
@@ -48,7 +49,7 @@ pub fn codegen_block(&mut self, bb: mir::BasicBlock) {
     }
 
     fn codegen_terminator(&mut self,
-                        mut bx: Builder<'a, 'tcx>,
+                        mut bx: Builder<'a, 'll, 'tcx>,
                         bb: mir::BasicBlock,
                         terminator: &mir::Terminator<'tcx>)
     {
@@ -97,7 +98,7 @@ fn codegen_terminator(&mut self,
             }
         };
 
-        let funclet_br = |this: &mut Self, bx: Builder, target: mir::BasicBlock| {
+        let funclet_br = |this: &mut Self, bx: Builder<'_, 'll, '_>, target: mir::BasicBlock| {
             let (lltarget, is_cleanupret) = lltarget(this, target);
             if is_cleanupret {
                 // micro-optimization: generate a `ret` rather than a jump
@@ -110,11 +111,11 @@ fn codegen_terminator(&mut self,
 
         let do_call = |
             this: &mut Self,
-            bx: Builder<'a, 'tcx>,
+            bx: Builder<'a, 'll, 'tcx>,
             fn_ty: FnType<'tcx, Ty<'tcx>>,
-            fn_ptr: ValueRef,
-            llargs: &[ValueRef],
-            destination: Option<(ReturnDest<'tcx>, mir::BasicBlock)>,
+            fn_ptr: &'ll Value,
+            llargs: &[&'ll Value],
+            destination: Option<(ReturnDest<'ll, 'tcx>, mir::BasicBlock)>,
             cleanup: Option<mir::BasicBlock>
         | {
             if let Some(cleanup) = cleanup {
@@ -285,8 +286,14 @@ fn codegen_terminator(&mut self,
                 }
 
                 let place = self.codegen_place(&bx, location);
-                let mut args: &[_] = &[place.llval, place.llextra];
-                args = &args[..1 + place.has_extra() as usize];
+                let (args1, args2);
+                let mut args = if let Some(llextra) = place.llextra {
+                    args2 = [place.llval, llextra];
+                    &args2[..]
+                } else {
+                    args1 = [place.llval];
+                    &args1[..]
+                };
                 let (drop_fn, fn_ty) = match ty.sty {
                     ty::TyDynamic(..) => {
                         let fn_ty = drop_fn.ty(bx.cx.tcx);
@@ -296,8 +303,9 @@ fn codegen_terminator(&mut self,
                             &sig,
                         );
                         let fn_ty = FnType::new_vtable(bx.cx, sig, &[]);
+                        let vtable = args[1];
                         args = &args[..1];
-                        (meth::DESTRUCTOR.get_fn(&bx, place.llextra, &fn_ty), fn_ty)
+                        (meth::DESTRUCTOR.get_fn(&bx, vtable, &fn_ty), fn_ty)
                     }
                     _ => {
                         (callee::get_fn(bx.cx, drop_fn),
@@ -627,9 +635,9 @@ fn codegen_terminator(&mut self,
     }
 
     fn codegen_argument(&mut self,
-                      bx: &Builder<'a, 'tcx>,
-                      op: OperandRef<'tcx>,
-                      llargs: &mut Vec<ValueRef>,
+                      bx: &Builder<'a, 'll, 'tcx>,
+                      op: OperandRef<'ll, 'tcx>,
+                      llargs: &mut Vec<&'ll Value>,
                       arg: &ArgType<'tcx, Ty<'tcx>>) {
         // Fill padding with undef value, where applicable.
         if let Some(ty) = arg.pad {
@@ -706,9 +714,9 @@ fn codegen_argument(&mut self,
     }
 
     fn codegen_arguments_untupled(&mut self,
-                                bx: &Builder<'a, 'tcx>,
+                                bx: &Builder<'a, 'll, 'tcx>,
                                 operand: &mir::Operand<'tcx>,
-                                llargs: &mut Vec<ValueRef>,
+                                llargs: &mut Vec<&'ll Value>,
                                 args: &[ArgType<'tcx, Ty<'tcx>>]) {
         let tuple = self.codegen_operand(bx, operand);
 
@@ -728,7 +736,7 @@ fn codegen_arguments_untupled(&mut self,
         }
     }
 
-    fn get_personality_slot(&mut self, bx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
+    fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'ll, 'tcx> {
         let cx = bx.cx;
         if let Some(slot) = self.personality_slot {
             slot
@@ -746,7 +754,7 @@ fn get_personality_slot(&mut self, bx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> {
     /// Return the landingpad wrapper around the given basic block
     ///
     /// No-op in MSVC SEH scheme.
-    fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef {
+    fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> &'ll BasicBlock {
         if let Some(block) = self.landing_pads[target_bb] {
             return block;
         }
@@ -757,7 +765,7 @@ fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef {
         landing_pad
     }
 
-    fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef {
+    fn landing_pad_uncached(&mut self, target_bb: &'ll BasicBlock) -> &'ll BasicBlock {
         if base::wants_msvc_seh(self.cx.sess()) {
             span_bug!(self.mir.span, "landing pad was not inserted?")
         }
@@ -777,12 +785,12 @@ fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef {
         bx.llbb()
     }
 
-    fn landing_pad_type(&self) -> Type {
+    fn landing_pad_type(&self) -> &'ll Type {
         let cx = self.cx;
         Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false)
     }
 
-    fn unreachable_block(&mut self) -> BasicBlockRef {
+    fn unreachable_block(&mut self) -> &'ll BasicBlock {
         self.unreachable_block.unwrap_or_else(|| {
             let bl = self.new_block("unreachable");
             bl.unreachable();
@@ -791,20 +799,20 @@ fn unreachable_block(&mut self) -> BasicBlockRef {
         })
     }
 
-    pub fn new_block(&self, name: &str) -> Builder<'a, 'tcx> {
+    pub fn new_block(&self, name: &str) -> Builder<'a, 'll, 'tcx> {
         Builder::new_block(self.cx, self.llfn, name)
     }
 
-    pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> {
+    pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'll, 'tcx> {
         let bx = Builder::with_cx(self.cx);
         bx.position_at_end(self.blocks[bb]);
         bx
     }
 
-    fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>,
+    fn make_return_dest(&mut self, bx: &Builder<'a, 'll, 'tcx>,
                         dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx, Ty<'tcx>>,
-                        llargs: &mut Vec<ValueRef>, is_intrinsic: bool)
-                        -> ReturnDest<'tcx> {
+                        llargs: &mut Vec<&'ll Value>, is_intrinsic: bool)
+                        -> ReturnDest<'ll, 'tcx> {
         // If the return is ignored, we can just return a do-nothing ReturnDest
         if fn_ret.is_ignore() {
             return ReturnDest::Nothing;
@@ -857,7 +865,7 @@ fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>,
         }
     }
 
-    fn codegen_transmute(&mut self, bx: &Builder<'a, 'tcx>,
+    fn codegen_transmute(&mut self, bx: &Builder<'a, 'll, 'tcx>,
                        src: &mir::Operand<'tcx>,
                        dst: &mir::Place<'tcx>) {
         if let mir::Place::Local(index) = *dst {
@@ -884,9 +892,9 @@ fn codegen_transmute(&mut self, bx: &Builder<'a, 'tcx>,
         }
     }
 
-    fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'tcx>,
+    fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>,
                             src: &mir::Operand<'tcx>,
-                            dst: PlaceRef<'tcx>) {
+                            dst: PlaceRef<'ll, 'tcx>) {
         let src = self.codegen_operand(bx, src);
         let llty = src.layout.llvm_type(bx.cx);
         let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to());
@@ -897,10 +905,10 @@ fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'tcx>,
 
     // Stores the return value of a function call into it's final location.
     fn store_return(&mut self,
-                    bx: &Builder<'a, 'tcx>,
-                    dest: ReturnDest<'tcx>,
+                    bx: &Builder<'a, 'll, 'tcx>,
+                    dest: ReturnDest<'ll, 'tcx>,
                     ret_ty: &ArgType<'tcx, Ty<'tcx>>,
-                    llval: ValueRef) {
+                    llval: &'ll Value) {
         use self::ReturnDest::*;
 
         match dest {
@@ -929,13 +937,13 @@ fn store_return(&mut self,
     }
 }
 
-enum ReturnDest<'tcx> {
+enum ReturnDest<'ll, 'tcx> {
     // Do nothing, the return value is indirect or ignored
     Nothing,
     // Store the return value to the pointer
-    Store(PlaceRef<'tcx>),
+    Store(PlaceRef<'ll, 'tcx>),
     // Stores an indirect return value to an operand local place
-    IndirectOperand(PlaceRef<'tcx>, mir::Local),
+    IndirectOperand(PlaceRef<'ll, 'tcx>, mir::Local),
     // Stores a direct return value to an operand local place
     DirectOperand(mir::Local)
 }
index 0d682d5d6f6a1478fc86286a5ab68379a95b7abd..267db4467c21a23e376e7c89c9099404c000628d 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef};
+use llvm;
 use rustc::mir::interpret::ConstEvalErr;
 use rustc_mir::interpret::{read_target_uint, const_val_field};
 use rustc::hir::def_id::DefId;
 use type_::Type;
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
+use value::Value;
 
 use super::super::callee;
 use super::FunctionCx;
 
-pub fn scalar_to_llvm(cx: &CodegenCx,
-                       cv: Scalar,
-                       layout: &layout::Scalar,
-                       llty: Type) -> ValueRef {
+pub fn scalar_to_llvm(
+    cx: &CodegenCx<'ll, '_>,
+    cv: Scalar,
+    layout: &layout::Scalar,
+    llty: &'ll Type,
+) -> &'ll Value {
     let bitsize = if layout.is_bool() { 1 } else { layout.value.size(cx).bits() };
     match cv {
-        Scalar::Bits { defined, .. } if (defined as u64) < bitsize || defined == 0 => {
-            C_undef(Type::ix(cx, bitsize))
+        Scalar::Bits { size: 0, .. } => {
+            assert_eq!(0, layout.value.size(cx).bytes());
+            C_undef(Type::ix(cx, 0))
         },
-        Scalar::Bits { bits, .. } => {
+        Scalar::Bits { bits, size } => {
+            assert_eq!(size as u64, layout.value.size(cx).bytes());
             let llval = C_uint_big(Type::ix(cx, bitsize), bits);
             if layout.value == layout::Pointer {
-                unsafe { llvm::LLVMConstIntToPtr(llval, llty.to_ref()) }
+                unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
             } else {
                 consts::bitcast(llval, llty)
             }
@@ -73,7 +78,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx,
                 1,
             ) };
             if layout.value != layout::Pointer {
-                unsafe { llvm::LLVMConstPtrToInt(llval, llty.to_ref()) }
+                unsafe { llvm::LLVMConstPtrToInt(llval, llty) }
             } else {
                 consts::bitcast(llval, llty)
             }
@@ -81,7 +86,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx,
     }
 }
 
-pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
+pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
     let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
     let layout = cx.data_layout();
     let pointer_size = layout.pointer_size.bytes() as usize;
@@ -116,10 +121,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
     C_struct(cx, &llvals, true)
 }
 
-pub fn codegen_static_initializer<'a, 'tcx>(
-    cx: &CodegenCx<'a, 'tcx>,
+pub fn codegen_static_initializer(
+    cx: &CodegenCx<'ll, 'tcx>,
     def_id: DefId,
-) -> Result<(ValueRef, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>> {
+) -> Result<(&'ll Value, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>> {
     let instance = ty::Instance::mono(cx.tcx, def_id);
     let cid = GlobalId {
         instance,
@@ -135,10 +140,10 @@ pub fn codegen_static_initializer<'a, 'tcx>(
     Ok((const_alloc_to_llvm(cx, alloc), alloc))
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     fn fully_evaluate(
         &mut self,
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         constant: &'tcx ty::Const<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         match constant.val {
@@ -158,7 +163,7 @@ fn fully_evaluate(
 
     pub fn eval_mir_constant(
         &mut self,
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         constant: &mir::Constant<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         let c = self.monomorphize(&constant.literal);
@@ -168,11 +173,11 @@ pub fn eval_mir_constant(
     /// process constant containing SIMD shuffle indices
     pub fn simd_shuffle_indices(
         &mut self,
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         span: Span,
         ty: Ty<'tcx>,
         constant: Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>,
-    ) -> (ValueRef, Ty<'tcx>) {
+    ) -> (&'ll Value, Ty<'tcx>) {
         constant
             .and_then(|c| {
                 let field_ty = c.ty.builtin_index().unwrap();
@@ -180,7 +185,7 @@ pub fn simd_shuffle_indices(
                     ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()),
                     ref other => bug!("invalid simd shuffle type: {}", other),
                 };
-                let values: Result<Vec<ValueRef>, Lrc<_>> = (0..fields).map(|field| {
+                let values: Result<Vec<_>, Lrc<_>> = (0..fields).map(|field| {
                     let field = const_val_field(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
@@ -189,7 +194,7 @@ pub fn simd_shuffle_indices(
                         mir::Field::new(field as usize),
                         c,
                     )?;
-                    if let Some(prim) = field.to_scalar() {
+                    if let Some(prim) = field.val.try_to_scalar() {
                         let layout = bx.cx.layout_of(field_ty);
                         let scalar = match layout.abi {
                             layout::Abi::Scalar(ref x) => x,
index 312939408c62cf0f9badab6166f6570383802120..8fdb67f5930cecb8f05d9eea7d86df76a79fd7aa 100644 (file)
 
 use common::{C_i32, C_null};
 use libc::c_uint;
-use llvm::{self, ValueRef, BasicBlockRef};
+use llvm::{self, BasicBlock};
 use llvm::debuginfo::DIScope;
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc::mir::{self, Mir};
 use rustc::ty::subst::Substs;
-use rustc::session::config::FullDebugInfo;
+use rustc::session::config::DebugInfo;
 use base;
 use builder::Builder;
 use common::{CodegenCx, Funclet};
 use monomorphize::Instance;
 use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
 use type_::Type;
+use value::Value;
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
 use syntax::symbol::keywords;
 
 use std::iter;
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
 pub use self::constant::codegen_static_initializer;
 use self::operand::{OperandRef, OperandValue};
 
 /// Master context for codegenning from MIR.
-pub struct FunctionCx<'a, 'tcx:'a> {
+pub struct FunctionCx<'a, 'll: 'a, 'tcx: 'll> {
     instance: Instance<'tcx>,
 
     mir: &'a mir::Mir<'tcx>,
 
-    debug_context: debuginfo::FunctionDebugContext,
+    debug_context: FunctionDebugContext<'ll>,
 
-    llfn: ValueRef,
+    llfn: &'ll Value,
 
-    cx: &'a CodegenCx<'a, 'tcx>,
+    cx: &'a CodegenCx<'ll, 'tcx>,
 
     fn_ty: FnType<'tcx, Ty<'tcx>>,
 
@@ -62,24 +63,24 @@ pub struct FunctionCx<'a, 'tcx:'a> {
     /// don't really care about it very much. Anyway, this value
     /// contains an alloca into which the personality is stored and
     /// then later loaded when generating the DIVERGE_BLOCK.
-    personality_slot: Option<PlaceRef<'tcx>>,
+    personality_slot: Option<PlaceRef<'ll, 'tcx>>,
 
     /// A `Block` for each MIR `BasicBlock`
-    blocks: IndexVec<mir::BasicBlock, BasicBlockRef>,
+    blocks: IndexVec<mir::BasicBlock, &'ll BasicBlock>,
 
     /// The funclet status of each basic block
     cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
 
     /// When targeting MSVC, this stores the cleanup info for each funclet
     /// BB. This is initialized as we compute the funclets' head block in RPO.
-    funclets: &'a IndexVec<mir::BasicBlock, Option<Funclet>>,
+    funclets: &'a IndexVec<mir::BasicBlock, Option<Funclet<'ll>>>,
 
     /// This stores the landing-pad block for a given BB, computed lazily on GNU
     /// and eagerly on MSVC.
-    landing_pads: IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
+    landing_pads: IndexVec<mir::BasicBlock, Option<&'ll BasicBlock>>,
 
     /// Cached unreachable block
-    unreachable_block: Option<BasicBlockRef>,
+    unreachable_block: Option<&'ll BasicBlock>,
 
     /// The location where each MIR arg/var/tmp/ret is stored. This is
     /// usually an `PlaceRef` representing an alloca, but not always:
@@ -96,16 +97,16 @@ pub struct FunctionCx<'a, 'tcx:'a> {
     ///
     /// Avoiding allocs can also be important for certain intrinsics,
     /// notably `expect`.
-    locals: IndexVec<mir::Local, LocalRef<'tcx>>,
+    locals: IndexVec<mir::Local, LocalRef<'ll, 'tcx>>,
 
     /// Debug information for MIR scopes.
-    scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope>,
+    scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
 
     /// If this function is being monomorphized, this contains the type substitutions used.
     param_substs: &'tcx Substs<'tcx>,
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn monomorphize<T>(&self, value: &T) -> T
         where T: TypeFoldable<'tcx>
     {
@@ -116,12 +117,12 @@ pub fn monomorphize<T>(&self, value: &T) -> T
         )
     }
 
-    pub fn set_debug_loc(&mut self, bx: &Builder, source_info: mir::SourceInfo) {
+    pub fn set_debug_loc(&mut self, bx: &Builder<'_, 'll, '_>, source_info: mir::SourceInfo) {
         let (scope, span) = self.debug_loc(source_info);
         debuginfo::set_source_location(&self.debug_context, bx, scope, span);
     }
 
-    pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
+    pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (Option<&'ll DIScope>, Span) {
         // Bail out if debug info emission is not enabled.
         match self.debug_context {
             FunctionDebugContext::DebugInfoDisabled |
@@ -161,29 +162,29 @@ pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
     // corresponding to span's containing source scope.  If so, we need to create a DIScope
     // "extension" into that file.
     fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos)
-                               -> llvm::debuginfo::DIScope {
+                               -> Option<&'ll DIScope> {
         let scope_metadata = self.scopes[scope_id].scope_metadata;
         if pos < self.scopes[scope_id].file_start_pos ||
            pos >= self.scopes[scope_id].file_end_pos {
             let cm = self.cx.sess().codemap();
             let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
-            debuginfo::extend_scope_to_file(self.cx,
-                                            scope_metadata,
+            Some(debuginfo::extend_scope_to_file(self.cx,
+                                            scope_metadata.unwrap(),
                                             &cm.lookup_char_pos(pos).file,
-                                            defining_crate)
+                                            defining_crate))
         } else {
             scope_metadata
         }
     }
 }
 
-enum LocalRef<'tcx> {
-    Place(PlaceRef<'tcx>),
-    Operand(Option<OperandRef<'tcx>>),
+enum LocalRef<'ll, 'tcx> {
+    Place(PlaceRef<'ll, 'tcx>),
+    Operand(Option<OperandRef<'ll, 'tcx>>),
 }
 
-impl<'a, 'tcx> LocalRef<'tcx> {
-    fn new_operand(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> {
+impl LocalRef<'ll, 'tcx> {
+    fn new_operand(cx: &CodegenCx<'ll, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'ll, 'tcx> {
         if layout.is_zst() {
             // Zero-size temporaries aren't always initialized, which
             // doesn't matter because they don't contain data, but
@@ -197,9 +198,9 @@ fn new_operand(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tc
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub fn codegen_mir<'a, 'tcx: 'a>(
-    cx: &'a CodegenCx<'a, 'tcx>,
-    llfn: ValueRef,
+pub fn codegen_mir(
+    cx: &'a CodegenCx<'ll, 'tcx>,
+    llfn: &'ll Value,
     mir: &'a Mir<'tcx>,
     instance: Instance<'tcx>,
     sig: ty::FnSig<'tcx>,
@@ -218,7 +219,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
     // Allocate a `Block` for every basic block, except
     // the start block, if nothing loops back to it.
     let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
-    let block_bxs: IndexVec<mir::BasicBlock, BasicBlockRef> =
+    let block_bxs: IndexVec<mir::BasicBlock, &'ll BasicBlock> =
         mir.basic_blocks().indices().map(|bb| {
             if bb == mir::START_BLOCK && !reentrant_start_block {
                 bx.llbb()
@@ -266,7 +267,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
             if let Some(name) = decl.name {
                 // User variable
                 let debug_scope = fx.scopes[decl.visibility_scope];
-                let dbg = debug_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo;
+                let dbg = debug_scope.is_valid() && bx.sess().opts.debuginfo == DebugInfo::Full;
 
                 if !memory_locals.contains(local) && !dbg {
                     debug!("alloc: {:?} ({}) -> operand", local, name);
@@ -280,7 +281,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
                         span: decl.source_info.span,
                         scope: decl.visibility_scope,
                     });
-                    declare_local(&bx, &fx.debug_context, name, layout.ty, scope,
+                    declare_local(&bx, &fx.debug_context, name, layout.ty, scope.unwrap(),
                         VariableAccess::DirectVariable { alloca: place.llval },
                         VariableKind::LocalVariable, span);
                 }
@@ -322,7 +323,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
     debuginfo::start_emitting_source_locations(&fx.debug_context);
 
     let rpo = traversal::reverse_postorder(&mir);
-    let mut visited = BitVector::new(mir.basic_blocks().len());
+    let mut visited = BitArray::new(mir.basic_blocks().len());
 
     // Codegen the body of each block using reverse postorder
     for (bb, _) in rpo {
@@ -343,13 +344,13 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
     }
 }
 
-fn create_funclets<'a, 'tcx>(
+fn create_funclets(
     mir: &'a Mir<'tcx>,
-    bx: &Builder<'a, 'tcx>,
+    bx: &Builder<'a, 'll, 'tcx>,
     cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
-    block_bxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
-    -> (IndexVec<mir::BasicBlock, Option<BasicBlockRef>>,
-        IndexVec<mir::BasicBlock, Option<Funclet>>)
+    block_bxs: &IndexVec<mir::BasicBlock, &'ll BasicBlock>)
+    -> (IndexVec<mir::BasicBlock, Option<&'ll BasicBlock>>,
+        IndexVec<mir::BasicBlock, Option<Funclet<'ll>>>)
 {
     block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
         match *cleanup_kind {
@@ -409,14 +410,15 @@ fn create_funclets<'a, 'tcx>(
     }).unzip()
 }
 
-/// Produce, for each argument, a `ValueRef` pointing at the
+/// Produce, for each argument, a `Value` pointing at the
 /// argument's value. As arguments are places, these are always
 /// indirect.
-fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
-                            fx: &FunctionCx<'a, 'tcx>,
-                            scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope>,
-                            memory_locals: &BitVector<mir::Local>)
-                            -> Vec<LocalRef<'tcx>> {
+fn arg_local_refs(
+    bx: &Builder<'a, 'll, 'tcx>,
+    fx: &FunctionCx<'a, 'll, 'tcx>,
+    scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
+    memory_locals: &BitArray<mir::Local>,
+) -> Vec<LocalRef<'ll, 'tcx>> {
     let mir = fx.mir;
     let tcx = bx.tcx();
     let mut idx = 0;
@@ -424,8 +426,8 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
     // Get the argument scope, if it exists and if we need it.
     let arg_scope = scopes[mir::OUTERMOST_SOURCE_SCOPE];
-    let arg_scope = if arg_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo {
-        Some(arg_scope.scope_metadata)
+    let arg_scope = if bx.sess().opts.debuginfo == DebugInfo::Full {
+        arg_scope.scope_metadata
     } else {
         None
     };
index c433df51110e352b9cabc0b41418abd8858df37e..f8166ee6491472afcb6275a28ca2882193b377f6 100644 (file)
@@ -8,10 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::ValueRef;
 use rustc::mir::interpret::ConstEvalErr;
 use rustc::mir;
-use rustc::mir::interpret::ConstValue;
+use rustc::mir::interpret::{ConstValue, ScalarMaybeUndef};
 use rustc::ty;
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
 use rustc_data_structures::indexed_vec::Idx;
@@ -24,7 +23,6 @@
 use type_of::LayoutLlvmExt;
 
 use std::fmt;
-use std::ptr;
 
 use super::{FunctionCx, LocalRef};
 use super::constant::scalar_to_llvm;
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
 /// safety check.
-#[derive(Copy, Clone)]
-pub enum OperandValue {
+#[derive(Copy, Clone, Debug)]
+pub enum OperandValue<'ll> {
     /// A reference to the actual operand. The data is guaranteed
     /// to be valid for the operand's lifetime.
-    Ref(ValueRef, Align),
+    Ref(&'ll Value, Align),
     /// A single LLVM value.
-    Immediate(ValueRef),
+    Immediate(&'ll Value),
     /// A pair of immediate LLVM values. Used by fat pointers too.
-    Pair(ValueRef, ValueRef)
-}
-
-impl fmt::Debug for OperandValue {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            OperandValue::Ref(r, align) => {
-                write!(f, "Ref({:?}, {:?})", Value(r), align)
-            }
-            OperandValue::Immediate(i) => {
-                write!(f, "Immediate({:?})", Value(i))
-            }
-            OperandValue::Pair(a, b) => {
-                write!(f, "Pair({:?}, {:?})", Value(a), Value(b))
-            }
-        }
-    }
+    Pair(&'ll Value, &'ll Value)
 }
 
 /// An `OperandRef` is an "SSA" reference to a Rust value, along with
@@ -69,23 +51,23 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 /// directly is sure to cause problems -- use `OperandRef::store`
 /// instead.
 #[derive(Copy, Clone)]
-pub struct OperandRef<'tcx> {
+pub struct OperandRef<'ll, 'tcx> {
     // The value.
-    pub val: OperandValue,
+    pub val: OperandValue<'ll>,
 
     // The layout of value, based on its Rust type.
     pub layout: TyLayout<'tcx>,
 }
 
-impl<'tcx> fmt::Debug for OperandRef<'tcx> {
+impl fmt::Debug for OperandRef<'ll, 'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout)
     }
 }
 
-impl<'a, 'tcx> OperandRef<'tcx> {
-    pub fn new_zst(cx: &CodegenCx<'a, 'tcx>,
-                   layout: TyLayout<'tcx>) -> OperandRef<'tcx> {
+impl OperandRef<'ll, 'tcx> {
+    pub fn new_zst(cx: &CodegenCx<'ll, 'tcx>,
+                   layout: TyLayout<'tcx>) -> OperandRef<'ll, 'tcx> {
         assert!(layout.is_zst());
         OperandRef {
             val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))),
@@ -93,9 +75,9 @@ pub fn new_zst(cx: &CodegenCx<'a, 'tcx>,
         }
     }
 
-    pub fn from_const(bx: &Builder<'a, 'tcx>,
+    pub fn from_const(bx: &Builder<'a, 'll, 'tcx>,
                       val: &'tcx ty::Const<'tcx>)
-                      -> Result<OperandRef<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
+                      -> Result<OperandRef<'ll, 'tcx>, Lrc<ConstEvalErr<'tcx>>> {
         let layout = bx.cx.layout_of(val.ty);
 
         if layout.is_zst() {
@@ -128,12 +110,16 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
                     a_scalar,
                     layout.scalar_pair_element_llvm_type(bx.cx, 0, true),
                 );
-                let b_llval = scalar_to_llvm(
-                    bx.cx,
-                    b,
-                    b_scalar,
-                    layout.scalar_pair_element_llvm_type(bx.cx, 1, true),
-                );
+                let b_layout = layout.scalar_pair_element_llvm_type(bx.cx, 1, true);
+                let b_llval = match b {
+                    ScalarMaybeUndef::Scalar(b) => scalar_to_llvm(
+                        bx.cx,
+                        b,
+                        b_scalar,
+                        b_layout,
+                    ),
+                    ScalarMaybeUndef::Undef => C_undef(b_layout),
+                };
                 OperandValue::Pair(a_llval, b_llval)
             },
             ConstValue::ByRef(alloc, offset) => {
@@ -149,19 +135,19 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
 
     /// Asserts that this operand refers to a scalar and returns
     /// a reference to its value.
-    pub fn immediate(self) -> ValueRef {
+    pub fn immediate(self) -> &'ll Value {
         match self.val {
             OperandValue::Immediate(s) => s,
             _ => bug!("not immediate: {:?}", self)
         }
     }
 
-    pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> {
+    pub fn deref(self, cx: &CodegenCx<'ll, 'tcx>) -> PlaceRef<'ll, 'tcx> {
         let projected_ty = self.layout.ty.builtin_deref(true)
             .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty;
         let (llptr, llextra) = match self.val {
-            OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
-            OperandValue::Pair(llptr, llextra) => (llptr, llextra),
+            OperandValue::Immediate(llptr) => (llptr, None),
+            OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
             OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
         };
         let layout = cx.layout_of(projected_ty);
@@ -175,7 +161,7 @@ pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> {
 
     /// If this operand is a `Pair`, we return an aggregate with the two values.
     /// For other cases, see `immediate`.
-    pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef {
+    pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'll, 'tcx>) -> &'ll Value {
         if let OperandValue::Pair(a, b) = self.val {
             let llty = self.layout.llvm_type(bx.cx);
             debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}",
@@ -191,10 +177,10 @@ pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef {
     }
 
     /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`.
-    pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>,
-                                         llval: ValueRef,
+    pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'll, 'tcx>,
+                                         llval: &'ll Value,
                                          layout: TyLayout<'tcx>)
-                                         -> OperandRef<'tcx> {
+                                         -> OperandRef<'ll, 'tcx> {
         let val = if let layout::Abi::ScalarPair(ref a, ref b) = layout.abi {
             debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}",
                     llval, layout);
@@ -209,7 +195,7 @@ pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>,
         OperandRef { val, layout }
     }
 
-    pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> {
+    pub fn extract_field(&self, bx: &Builder<'a, 'll, 'tcx>, i: usize) -> OperandRef<'ll, 'tcx> {
         let field = self.layout.field(bx.cx, i);
         let offset = self.layout.fields.offset(i);
 
@@ -267,24 +253,29 @@ pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx
     }
 }
 
-impl<'a, 'tcx> OperandValue {
-    pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+impl OperandValue<'ll> {
+    pub fn store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::empty());
     }
 
-    pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+    pub fn volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::VOLATILE);
     }
 
-    pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+    pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED);
     }
 
-    pub fn nontemporal_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+    pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL);
     }
 
-    fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: MemFlags) {
+    fn store_with_flags(
+        self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        dest: PlaceRef<'ll, 'tcx>,
+        flags: MemFlags,
+    ) {
         debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
         // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
         // value is through `undef`, and store itself is useless.
@@ -311,11 +302,11 @@ fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: M
     }
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     fn maybe_codegen_consume_direct(&mut self,
-                                  bx: &Builder<'a, 'tcx>,
+                                  bx: &Builder<'a, 'll, 'tcx>,
                                   place: &mir::Place<'tcx>)
-                                   -> Option<OperandRef<'tcx>>
+                                   -> Option<OperandRef<'ll, 'tcx>>
     {
         debug!("maybe_codegen_consume_direct(place={:?})", place);
 
@@ -361,9 +352,9 @@ fn maybe_codegen_consume_direct(&mut self,
     }
 
     pub fn codegen_consume(&mut self,
-                         bx: &Builder<'a, 'tcx>,
+                         bx: &Builder<'a, 'll, 'tcx>,
                          place: &mir::Place<'tcx>)
-                         -> OperandRef<'tcx>
+                         -> OperandRef<'ll, 'tcx>
     {
         debug!("codegen_consume(place={:?})", place);
 
@@ -385,9 +376,9 @@ pub fn codegen_consume(&mut self,
     }
 
     pub fn codegen_operand(&mut self,
-                         bx: &Builder<'a, 'tcx>,
+                         bx: &Builder<'a, 'll, 'tcx>,
                          operand: &mir::Operand<'tcx>)
-                         -> OperandRef<'tcx>
+                         -> OperandRef<'ll, 'tcx>
     {
         debug!("codegen_operand(operand={:?})", operand);
 
index 9abf9077a9577f4d6b48672f3ca3463a9c0712f6..abc3dbdab2f5b04d307bfce1424d717814499cf1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef, LLVMConstInBoundsGEP};
+use llvm::{self, LLVMConstInBoundsGEP};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size};
 use rustc::mir;
 use glue;
 use mir::constant::const_alloc_to_llvm;
 
-use std::ptr;
-
 use super::{FunctionCx, LocalRef};
 use super::operand::{OperandRef, OperandValue};
 
 #[derive(Copy, Clone, Debug)]
-pub struct PlaceRef<'tcx> {
+pub struct PlaceRef<'ll, 'tcx> {
     /// Pointer to the contents of the place
-    pub llval: ValueRef,
+    pub llval: &'ll Value,
 
     /// This place's extra data if it is unsized, or null
-    pub llextra: ValueRef,
+    pub llextra: Option<&'ll Value>,
 
     /// Monomorphized type of this place, including variant information
     pub layout: TyLayout<'tcx>,
@@ -44,25 +42,26 @@ pub struct PlaceRef<'tcx> {
     pub align: Align,
 }
 
-impl<'a, 'tcx> PlaceRef<'tcx> {
-    pub fn new_sized(llval: ValueRef,
-                     layout: TyLayout<'tcx>,
-                     align: Align)
-                     -> PlaceRef<'tcx> {
+impl PlaceRef<'ll, 'tcx> {
+    pub fn new_sized(
+        llval: &'ll Value,
+        layout: TyLayout<'tcx>,
+        align: Align,
+    ) -> PlaceRef<'ll, 'tcx> {
         PlaceRef {
             llval,
-            llextra: ptr::null_mut(),
+            llextra: None,
             layout,
             align
         }
     }
 
     pub fn from_const_alloc(
-        bx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'll, 'tcx>,
         layout: TyLayout<'tcx>,
         alloc: &mir::interpret::Allocation,
         offset: Size,
-    ) -> PlaceRef<'tcx> {
+    ) -> PlaceRef<'ll, 'tcx> {
         let init = const_alloc_to_llvm(bx.cx, alloc);
         let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");
 
@@ -75,19 +74,18 @@ pub fn from_const_alloc(
         PlaceRef::new_sized(llval, layout, alloc.align)
     }
 
-    pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str)
-                  -> PlaceRef<'tcx> {
+    pub fn alloca(bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, name: &str)
+                  -> PlaceRef<'ll, 'tcx> {
         debug!("alloca({:?}: {:?})", name, layout);
         let tmp = bx.alloca(layout.llvm_type(bx.cx), name, layout.align);
         Self::new_sized(tmp, layout, layout.align)
     }
 
-    pub fn len(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
+    pub fn len(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Value {
         if let layout::FieldPlacement::Array { count, .. } = self.layout.fields {
             if self.layout.is_unsized() {
-                assert!(self.has_extra());
                 assert_eq!(count, 0);
-                self.llextra
+                self.llextra.unwrap()
             } else {
                 C_usize(cx, count)
             }
@@ -96,14 +94,10 @@ pub fn len(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef {
         }
     }
 
-    pub fn has_extra(&self) -> bool {
-        !self.llextra.is_null()
-    }
-
-    pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
+    pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'ll, 'tcx> {
         debug!("PlaceRef::load: {:?}", self);
 
-        assert!(!self.has_extra());
+        assert_eq!(self.llextra, None);
 
         if self.layout.is_zst() {
             return OperandRef::new_zst(bx.cx, self.layout);
@@ -126,23 +120,21 @@ pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
         };
 
         let val = if self.layout.is_llvm_immediate() {
-            let mut const_llval = ptr::null_mut();
+            let mut const_llval = None;
             unsafe {
-                let global = llvm::LLVMIsAGlobalVariable(self.llval);
-                if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
-                    const_llval = llvm::LLVMGetInitializer(global);
+                if let Some(global) = llvm::LLVMIsAGlobalVariable(self.llval) {
+                    if llvm::LLVMIsGlobalConstant(global) == llvm::True {
+                        const_llval = llvm::LLVMGetInitializer(global);
+                    }
                 }
             }
-
-            let llval = if !const_llval.is_null() {
-                const_llval
-            } else {
+            let llval = const_llval.unwrap_or_else(|| {
                 let load = bx.load(self.llval, self.align);
                 if let layout::Abi::Scalar(ref scalar) = self.layout.abi {
                     scalar_load_metadata(load, scalar);
                 }
                 load
-            };
+            });
             OperandValue::Immediate(base::to_immediate(bx, llval, self.layout))
         } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi {
             let load = |i, scalar: &layout::Scalar| {
@@ -164,7 +156,7 @@ pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
     }
 
     /// Access a field, at a point when the value's case is known.
-    pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> {
+    pub fn project_field(self, bx: &Builder<'a, 'll, 'tcx>, ix: usize) -> PlaceRef<'ll, 'tcx> {
         let cx = bx.cx;
         let field = self.layout.field(cx, ix);
         let offset = self.layout.fields.offset(ix);
@@ -187,7 +179,7 @@ pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx>
                 llextra: if cx.type_has_metadata(field.ty) {
                     self.llextra
                 } else {
-                    ptr::null_mut()
+                    None
                 },
                 layout: field,
                 align,
@@ -199,9 +191,9 @@ pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx>
         //   * known alignment - sized types, [T], str or a foreign type
         //   * packed struct - there is no alignment padding
         match field.ty.sty {
-            _ if !self.has_extra() => {
+            _ if self.llextra.is_none() => {
                 debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
-                    ix, Value(self.llval));
+                    ix, self.llval);
                 return simple();
             }
             _ if !field.is_unsized() => return simple(),
@@ -249,7 +241,7 @@ pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx>
         let offset = bx.and(bx.add(unaligned_offset, align_sub_1),
         bx.neg(unsized_align));
 
-        debug!("struct_field_ptr: DST field offset: {:?}", Value(offset));
+        debug!("struct_field_ptr: DST field offset: {:?}", offset);
 
         // Cast and adjust pointer
         let byte_ptr = bx.pointercast(self.llval, Type::i8p(cx));
@@ -268,7 +260,7 @@ pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx>
     }
 
     /// Obtain the actual discriminant of a value.
-    pub fn codegen_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
+    pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value {
         let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
         if self.layout.abi == layout::Abi::Uninhabited {
             return C_undef(cast_to);
@@ -332,7 +324,7 @@ pub fn codegen_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Val
 
     /// Set the discriminant for a new value of the given case of the given
     /// representation.
-    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) {
+    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) {
         if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
             return;
         }
@@ -386,18 +378,18 @@ pub fn codegen_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) {
         }
     }
 
-    pub fn project_index(&self, bx: &Builder<'a, 'tcx>, llindex: ValueRef)
-                         -> PlaceRef<'tcx> {
+    pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value)
+                         -> PlaceRef<'ll, 'tcx> {
         PlaceRef {
             llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]),
-            llextra: ptr::null_mut(),
+            llextra: None,
             layout: self.layout.field(bx.cx, 0),
             align: self.align
         }
     }
 
-    pub fn project_downcast(&self, bx: &Builder<'a, 'tcx>, variant_index: usize)
-                            -> PlaceRef<'tcx> {
+    pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize)
+                            -> PlaceRef<'ll, 'tcx> {
         let mut downcast = *self;
         downcast.layout = self.layout.for_variant(bx.cx, variant_index);
 
@@ -408,20 +400,20 @@ pub fn project_downcast(&self, bx: &Builder<'a, 'tcx>, variant_index: usize)
         downcast
     }
 
-    pub fn storage_live(&self, bx: &Builder<'a, 'tcx>) {
+    pub fn storage_live(&self, bx: &Builder<'a, 'll, 'tcx>) {
         bx.lifetime_start(self.llval, self.layout.size);
     }
 
-    pub fn storage_dead(&self, bx: &Builder<'a, 'tcx>) {
+    pub fn storage_dead(&self, bx: &Builder<'a, 'll, 'tcx>) {
         bx.lifetime_end(self.llval, self.layout.size);
     }
 }
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_place(&mut self,
-                        bx: &Builder<'a, 'tcx>,
+                        bx: &Builder<'a, 'll, 'tcx>,
                         place: &mir::Place<'tcx>)
-                        -> PlaceRef<'tcx> {
+                        -> PlaceRef<'ll, 'tcx> {
         debug!("codegen_place(place={:?})", place);
 
         let cx = bx.cx;
@@ -513,9 +505,8 @@ pub fn codegen_place(&mut self,
                         subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
-                            assert!(cg_base.has_extra());
-                            subslice.llextra = bx.sub(cg_base.llextra,
-                                C_usize(bx.cx, (from as u64) + (to as u64)));
+                            subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(),
+                                C_usize(bx.cx, (from as u64) + (to as u64))));
                         }
 
                         // Cast the place pointer type to the new
index 2e81fc16a58388d935024ac40d25b4ff1cb59b32..dda33ae3fecdfde329941b07cc606f34322b9a85 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{self, ValueRef};
+use llvm;
 use rustc::ty::{self, Ty};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::{self, LayoutOf};
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_rvalue(&mut self,
-                        bx: Builder<'a, 'tcx>,
-                        dest: PlaceRef<'tcx>,
+                        bx: Builder<'a, 'll, 'tcx>,
+                        dest: PlaceRef<'ll, 'tcx>,
                         rvalue: &mir::Rvalue<'tcx>)
-                        -> Builder<'a, 'tcx>
+                        -> Builder<'a, 'll, 'tcx>
     {
         debug!("codegen_rvalue(dest.llval={:?}, rvalue={:?})",
-               Value(dest.llval), rvalue);
+               dest.llval, rvalue);
 
         match *rvalue {
            mir::Rvalue::Use(ref operand) => {
@@ -176,9 +176,9 @@ pub fn codegen_rvalue(&mut self,
     }
 
     pub fn codegen_rvalue_operand(&mut self,
-                                bx: Builder<'a, 'tcx>,
+                                bx: Builder<'a, 'll, 'tcx>,
                                 rvalue: &mir::Rvalue<'tcx>)
-                                -> (Builder<'a, 'tcx>, OperandRef<'tcx>)
+                                -> (Builder<'a, 'll, 'tcx>, OperandRef<'ll, 'tcx>)
     {
         assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue);
 
@@ -371,7 +371,7 @@ pub fn codegen_rvalue_operand(&mut self,
                 let val = if !bx.cx.type_has_metadata(ty) {
                     OperandValue::Immediate(cg_place.llval)
                 } else {
-                    OperandValue::Pair(cg_place.llval, cg_place.llextra)
+                    OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
                 };
                 (bx, OperandRef {
                     val,
@@ -511,10 +511,11 @@ pub fn codegen_rvalue_operand(&mut self,
         }
     }
 
-    fn evaluate_array_len(&mut self,
-                          bx: &Builder<'a, 'tcx>,
-                          place: &mir::Place<'tcx>) -> ValueRef
-    {
+    fn evaluate_array_len(
+        &mut self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        place: &mir::Place<'tcx>,
+    ) -> &'ll Value {
         // ZST are passed as operands and require special handling
         // because codegen_place() panics if Local is operand.
         if let mir::Place::Local(index) = *place {
@@ -530,12 +531,14 @@ fn evaluate_array_len(&mut self,
         return cg_value.len(bx.cx);
     }
 
-    pub fn codegen_scalar_binop(&mut self,
-                              bx: &Builder<'a, 'tcx>,
-                              op: mir::BinOp,
-                              lhs: ValueRef,
-                              rhs: ValueRef,
-                              input_ty: Ty<'tcx>) -> ValueRef {
+    pub fn codegen_scalar_binop(
+        &mut self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        op: mir::BinOp,
+        lhs: &'ll Value,
+        rhs: &'ll Value,
+        input_ty: Ty<'tcx>,
+    ) -> &'ll Value {
         let is_float = input_ty.is_fp();
         let is_signed = input_ty.is_signed();
         let is_nil = input_ty.is_nil();
@@ -596,15 +599,16 @@ pub fn codegen_scalar_binop(&mut self,
         }
     }
 
-    pub fn codegen_fat_ptr_binop(&mut self,
-                               bx: &Builder<'a, 'tcx>,
-                               op: mir::BinOp,
-                               lhs_addr: ValueRef,
-                               lhs_extra: ValueRef,
-                               rhs_addr: ValueRef,
-                               rhs_extra: ValueRef,
-                               _input_ty: Ty<'tcx>)
-                               -> ValueRef {
+    pub fn codegen_fat_ptr_binop(
+        &mut self,
+        bx: &Builder<'a, 'll, 'tcx>,
+        op: mir::BinOp,
+        lhs_addr: &'ll Value,
+        lhs_extra: &'ll Value,
+        rhs_addr: &'ll Value,
+        rhs_extra: &'ll Value,
+        _input_ty: Ty<'tcx>,
+    ) -> &'ll Value {
         match op {
             mir::BinOp::Eq => {
                 bx.and(
@@ -644,11 +648,11 @@ pub fn codegen_fat_ptr_binop(&mut self,
     }
 
     pub fn codegen_scalar_checked_binop(&mut self,
-                                      bx: &Builder<'a, 'tcx>,
+                                      bx: &Builder<'a, 'll, 'tcx>,
                                       op: mir::BinOp,
-                                      lhs: ValueRef,
-                                      rhs: ValueRef,
-                                      input_ty: Ty<'tcx>) -> OperandValue {
+                                      lhs: &'ll Value,
+                                      rhs: &'ll Value,
+                                      input_ty: Ty<'tcx>) -> OperandValue<'ll> {
         // This case can currently arise only from functions marked
         // with #[rustc_inherit_overflow_checks] and inlined from
         // another crate (mostly core::num generic/#[inline] fns),
@@ -721,7 +725,7 @@ enum OverflowOp {
     Add, Sub, Mul
 }
 
-fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef {
+fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder<'_, 'll, '_>, ty: Ty) -> &'ll Value {
     use syntax::ast::IntTy::*;
     use syntax::ast::UintTy::*;
     use rustc::ty::{TyInt, TyUint};
@@ -729,18 +733,8 @@ fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef {
     let tcx = bx.tcx();
 
     let new_sty = match ty.sty {
-        TyInt(Isize) => match &tcx.sess.target.target.target_pointer_width[..] {
-            "16" => TyInt(I16),
-            "32" => TyInt(I32),
-            "64" => TyInt(I64),
-            _ => panic!("unsupported target word size")
-        },
-        TyUint(Usize) => match &tcx.sess.target.target.target_pointer_width[..] {
-            "16" => TyUint(U16),
-            "32" => TyUint(U32),
-            "64" => TyUint(U64),
-            _ => panic!("unsupported target word size")
-        },
+        TyInt(Isize) => TyInt(tcx.sess.target.isize_ty),
+        TyUint(Usize) => TyUint(tcx.sess.target.usize_ty),
         ref t @ TyUint(_) | ref t @ TyInt(_) => t.clone(),
         _ => panic!("tried to get overflow intrinsic for op applied to non-int type")
     };
@@ -796,11 +790,11 @@ fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef {
     bx.cx.get_intrinsic(&name)
 }
 
-fn cast_int_to_float(bx: &Builder,
+fn cast_int_to_float(bx: &Builder<'_, 'll, '_>,
                      signed: bool,
-                     x: ValueRef,
-                     int_ty: Type,
-                     float_ty: Type) -> ValueRef {
+                     x: &'ll Value,
+                     int_ty: &'ll Type,
+                     float_ty: &'ll Type) -> &'ll Value {
     // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
     // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
     // LLVM's uitofp produces undef in those cases, so we manually check for that case.
@@ -826,11 +820,11 @@ fn cast_int_to_float(bx: &Builder,
     }
 }
 
-fn cast_float_to_int(bx: &Builder,
+fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
                      signed: bool,
-                     x: ValueRef,
-                     float_ty: Type,
-                     int_ty: Type) -> ValueRef {
+                     x: &'ll Value,
+                     float_ty: &'ll Type,
+                     int_ty: &'ll Type) -> &'ll Value {
     let fptosui_result = if signed {
         bx.fptosi(x, int_ty)
     } else {
@@ -859,14 +853,14 @@ fn cast_float_to_int(bx: &Builder,
     // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
     // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
     // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
-    fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: Type) -> (u128, u128) {
+    fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: &Type) -> (u128, u128) {
         let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
         assert_eq!(rounded_min.status, Status::OK);
         let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
         assert!(rounded_max.value.is_finite());
         (rounded_min.value.to_bits(), rounded_max.value.to_bits())
     }
-    fn int_max(signed: bool, int_ty: Type) -> u128 {
+    fn int_max(signed: bool, int_ty: &Type) -> u128 {
         let shift_amount = 128 - int_ty.int_width();
         if signed {
             i128::MAX as u128 >> shift_amount
@@ -874,7 +868,7 @@ fn int_max(signed: bool, int_ty: Type) -> u128 {
             u128::MAX >> shift_amount
         }
     }
-    fn int_min(signed: bool, int_ty: Type) -> i128 {
+    fn int_min(signed: bool, int_ty: &Type) -> i128 {
         if signed {
             i128::MIN >> (128 - int_ty.int_width())
         } else {
index c0cce297ef6a98263db3e01b2a8ccaf8b03cc4d9..06340a3e5d8b43f01e898c16bc782d94c00e7005 100644 (file)
 use super::FunctionCx;
 use super::LocalRef;
 
-impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
+impl FunctionCx<'a, 'll, 'tcx> {
     pub fn codegen_statement(&mut self,
-                           bx: Builder<'a, 'tcx>,
+                           bx: Builder<'a, 'll, 'tcx>,
                            statement: &mir::Statement<'tcx>)
-                           -> Builder<'a, 'tcx> {
+                           -> Builder<'a, 'll, 'tcx> {
         debug!("codegen_statement(statement={:?})", statement);
 
         self.set_debug_loc(&bx, statement.source_info);
index a77acc4f1756f016de71784f726a9a9c64412302..9fa7cc46aee5eb10387549ef5b5ee34194ef308f 100644 (file)
 
 #![allow(non_upper_case_globals)]
 
+pub use llvm::Type;
+
 use llvm;
-use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind};
-use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
+use llvm::{Bool, False, True, TypeKind};
 
 use context::CodegenCx;
 
 
 use std::ffi::CString;
 use std::fmt;
-use std::mem;
-use std::ptr;
 
 use libc::c_uint;
 
-#[derive(Clone, Copy, PartialEq)]
-#[repr(C)]
-pub struct Type {
-    rf: TypeRef
+impl PartialEq for Type {
+    fn eq(&self, other: &Self) -> bool {
+        self as *const _ == other as *const _
+    }
 }
 
 impl fmt::Debug for Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
-            llvm::LLVMRustWriteTypeToString(self.to_ref(), s);
+            llvm::LLVMRustWriteTypeToString(self, s);
         }).expect("non-UTF8 type description from LLVM"))
     }
 }
 
-macro_rules! ty {
-    ($e:expr) => ( Type::from_ref(unsafe { $e }))
-}
-
-/// Wrapper for LLVM TypeRef
 impl Type {
-    #[inline(always)]
-    pub fn from_ref(r: TypeRef) -> Type {
-        Type {
-            rf: r
+    pub fn void(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMVoidTypeInContext(cx.llcx)
         }
     }
 
-    #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
-    pub fn to_ref(&self) -> TypeRef {
-        self.rf
-    }
-
-    pub fn to_ref_slice(slice: &[Type]) -> &[TypeRef] {
-        unsafe { mem::transmute(slice) }
-    }
-
-    pub fn void(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMVoidTypeInContext(cx.llcx))
+    pub fn metadata(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMRustMetadataTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn metadata(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMRustMetadataTypeInContext(cx.llcx))
+    pub fn i1(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt1TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i1(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt1TypeInContext(cx.llcx))
+    pub fn i8(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt8TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i8(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
+    pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
+        unsafe {
+            llvm::LLVMInt8TypeInContext(llcx)
+        }
     }
 
-    pub fn i8_llcx(llcx: ContextRef) -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(llcx))
+    pub fn i16(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt16TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i16(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt16TypeInContext(cx.llcx))
+    pub fn i32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt32TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i32(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt32TypeInContext(cx.llcx))
+    pub fn i64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt64TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i64(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt64TypeInContext(cx.llcx))
+    pub fn i128(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(cx.llcx, 128)
+        }
     }
 
-    pub fn i128(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(cx.llcx, 128))
+    // Creates an integer type with the given number of bits, e.g. i24
+    pub fn ix(cx: &CodegenCx<'ll, '_>, num_bits: u64) -> &'ll Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint)
+        }
     }
 
     // Creates an integer type with the given number of bits, e.g. i24
-    pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint))
+    pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
+        }
     }
 
-    pub fn f32(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMFloatTypeInContext(cx.llcx))
+    pub fn f32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFloatTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn f64(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMDoubleTypeInContext(cx.llcx))
+    pub fn f64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMDoubleTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn bool(cx: &CodegenCx) -> Type {
+    pub fn bool(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i8(cx)
     }
 
-    pub fn char(cx: &CodegenCx) -> Type {
+    pub fn char(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i32(cx)
     }
 
-    pub fn i8p(cx: &CodegenCx) -> Type {
+    pub fn i8p(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i8(cx).ptr_to()
     }
 
-    pub fn i8p_llcx(llcx: ContextRef) -> Type {
+    pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
         Type::i8_llcx(llcx).ptr_to()
     }
 
-    pub fn isize(cx: &CodegenCx) -> Type {
-        match &cx.tcx.sess.target.target.target_pointer_width[..] {
-            "16" => Type::i16(cx),
-            "32" => Type::i32(cx),
-            "64" => Type::i64(cx),
-            tws => bug!("Unsupported target word size for int: {}", tws),
-        }
+    pub fn isize(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        cx.isize_ty
     }
 
-    pub fn c_int(cx: &CodegenCx) -> Type {
+    pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         match &cx.tcx.sess.target.target.target_c_int_width[..] {
             "16" => Type::i16(cx),
             "32" => Type::i32(cx),
@@ -145,7 +149,7 @@ pub fn c_int(cx: &CodegenCx) -> Type {
         }
     }
 
-    pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type {
+    pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type {
         match t {
             ast::IntTy::Isize => cx.isize_ty,
             ast::IntTy::I8 => Type::i8(cx),
@@ -156,7 +160,7 @@ pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type {
         }
     }
 
-    pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type {
+    pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type {
         match t {
             ast::UintTy::Usize => cx.isize_ty,
             ast::UintTy::U8 => Type::i8(cx),
@@ -167,93 +171,103 @@ pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type {
         }
     }
 
-    pub fn float_from_ty(cx: &CodegenCx, t: ast::FloatTy) -> Type {
+    pub fn float_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::FloatTy) -> &'ll Type {
         match t {
             ast::FloatTy::F32 => Type::f32(cx),
             ast::FloatTy::F64 => Type::f64(cx),
         }
     }
 
-    pub fn func(args: &[Type], ret: &Type) -> Type {
-        let slice: &[TypeRef] = Type::to_ref_slice(args);
-        ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(),
-                                   args.len() as c_uint, False))
+    pub fn func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFunctionType(ret, args.as_ptr(),
+                                   args.len() as c_uint, False)
+        }
     }
 
-    pub fn variadic_func(args: &[Type], ret: &Type) -> Type {
-        let slice: &[TypeRef] = Type::to_ref_slice(args);
-        ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(),
-                                   args.len() as c_uint, True))
+    pub fn variadic_func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFunctionType(ret, args.as_ptr(),
+                                   args.len() as c_uint, True)
+        }
     }
 
-    pub fn struct_(cx: &CodegenCx, els: &[Type], packed: bool) -> Type {
-        let els: &[TypeRef] = Type::to_ref_slice(els);
-        ty!(llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
+    pub fn struct_(cx: &CodegenCx<'ll, '_>, els: &[&'ll Type], packed: bool) -> &'ll Type {
+        unsafe {
+            llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
                                           els.len() as c_uint,
-                                          packed as Bool))
+                                          packed as Bool)
+        }
     }
 
-    pub fn named_struct(cx: &CodegenCx, name: &str) -> Type {
+    pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type {
         let name = CString::new(name).unwrap();
-        ty!(llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()))
+        unsafe {
+            llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr())
+        }
     }
 
 
-    pub fn array(ty: &Type, len: u64) -> Type {
-        ty!(llvm::LLVMRustArrayType(ty.to_ref(), len))
+    pub fn array(ty: &Type, len: u64) -> &Type {
+        unsafe {
+            llvm::LLVMRustArrayType(ty, len)
+        }
     }
 
-    pub fn vector(ty: &Type, len: u64) -> Type {
-        ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
+    pub fn vector(ty: &Type, len: u64) -> &Type {
+        unsafe {
+            llvm::LLVMVectorType(ty, len as c_uint)
+        }
     }
 
     pub fn kind(&self) -> TypeKind {
         unsafe {
-            llvm::LLVMRustGetTypeKind(self.to_ref())
+            llvm::LLVMRustGetTypeKind(self)
         }
     }
 
-    pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
-        let slice: &[TypeRef] = Type::to_ref_slice(els);
+    pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) {
         unsafe {
-            llvm::LLVMStructSetBody(self.to_ref(), slice.as_ptr(),
+            llvm::LLVMStructSetBody(self, els.as_ptr(),
                                     els.len() as c_uint, packed as Bool)
         }
     }
 
-    pub fn ptr_to(&self) -> Type {
-        ty!(llvm::LLVMPointerType(self.to_ref(), 0))
+    pub fn ptr_to(&self) -> &Type {
+        unsafe {
+            llvm::LLVMPointerType(self, 0)
+        }
     }
 
-    pub fn element_type(&self) -> Type {
+    pub fn element_type(&self) -> &Type {
         unsafe {
-            Type::from_ref(llvm::LLVMGetElementType(self.to_ref()))
+            llvm::LLVMGetElementType(self)
         }
     }
 
     /// Return the number of elements in `self` if it is a LLVM vector type.
     pub fn vector_length(&self) -> usize {
         unsafe {
-            llvm::LLVMGetVectorSize(self.to_ref()) as usize
+            llvm::LLVMGetVectorSize(self) as usize
         }
     }
 
-    pub fn func_params(&self) -> Vec<Type> {
+    pub fn func_params(&self) -> Vec<&Type> {
         unsafe {
-            let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize;
-            let mut args = vec![Type { rf: ptr::null_mut() }; n_args];
-            llvm::LLVMGetParamTypes(self.to_ref(),
-                                    args.as_mut_ptr() as *mut TypeRef);
+            let n_args = llvm::LLVMCountParamTypes(self) as usize;
+            let mut args = Vec::with_capacity(n_args);
+            llvm::LLVMGetParamTypes(self, args.as_mut_ptr());
+            args.set_len(n_args);
             args
         }
     }
 
     pub fn float_width(&self) -> usize {
         match self.kind() {
-            Float => 32,
-            Double => 64,
-            X86_FP80 => 80,
-            FP128 | PPC_FP128 => 128,
+            TypeKind::Float => 32,
+            TypeKind::Double => 64,
+            TypeKind::X86_FP80 => 80,
+            TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
             _ => bug!("llvm_float_width called on a non-float type")
         }
     }
@@ -261,11 +275,11 @@ pub fn float_width(&self) -> usize {
     /// Retrieve the bit width of the integer type `self`.
     pub fn int_width(&self) -> u64 {
         unsafe {
-            llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64
+            llvm::LLVMGetIntTypeWidth(self) as u64
         }
     }
 
-    pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type {
+    pub fn from_integer(cx: &CodegenCx<'ll, '_>, i: layout::Integer) -> &'ll Type {
         use rustc::ty::layout::Integer::*;
         match i {
             I8 => Type::i8(cx),
@@ -278,7 +292,7 @@ pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type {
 
     /// Return a LLVM type that has at most the required alignment,
     /// as a conservative approximation for unknown pointee types.
-    pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type {
+    pub fn pointee_for_abi_align(cx: &CodegenCx<'ll, '_>, align: Align) -> &'ll Type {
         // FIXME(eddyb) We could find a better approximation if ity.align < align.
         let ity = layout::Integer::approximate_abi_align(cx, align);
         Type::from_integer(cx, ity)
@@ -286,15 +300,17 @@ pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type {
 
     /// Return a LLVM type that has at most the required alignment,
     /// and exactly the required size, as a best-effort padding array.
-    pub fn padding_filler(cx: &CodegenCx, size: Size, align: Align) -> Type {
+    pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type {
         let unit = layout::Integer::approximate_abi_align(cx, align);
         let size = size.bytes();
         let unit_size = unit.size().bytes();
         assert_eq!(size % unit_size, 0);
-        Type::array(&Type::from_integer(cx, unit), size / unit_size)
+        Type::array(Type::from_integer(cx, unit), size / unit_size)
     }
 
-    pub fn x86_mmx(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx))
+    pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMX86MMXTypeInContext(cx.llcx)
+        }
     }
 }
index 4728d7717a1e1d3f874ee69660a8c9c357c848db..5fd4f15acd1574c719cda4a117994e0c2bd0f3b6 100644 (file)
@@ -23,8 +23,8 @@
 
 fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 layout: TyLayout<'tcx>,
-                                defer: &mut Option<(Type, TyLayout<'tcx>)>)
-                                -> Type {
+                                defer: &mut Option<(&'a Type, TyLayout<'tcx>)>)
+                                -> &'a Type {
     match layout.abi {
         layout::Abi::Scalar(_) => bug!("handled elsewhere"),
         layout::Abi::Vector { ref element, count } => {
@@ -42,7 +42,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 return Type::x86_mmx(cx)
             } else {
                 let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
-                return Type::vector(&element, count);
+                return Type::vector(element, count);
             }
         }
         layout::Abi::ScalarPair(..) => {
@@ -96,7 +96,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             }
         }
         layout::FieldPlacement::Array { count, .. } => {
-            Type::array(&layout.field(cx, 0).llvm_type(cx), count)
+            Type::array(layout.field(cx, 0).llvm_type(cx), count)
         }
         layout::FieldPlacement::Arbitrary { .. } => {
             match name {
@@ -116,14 +116,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
 fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              layout: TyLayout<'tcx>)
-                             -> (Vec<Type>, bool) {
+                             -> (Vec<&'a Type>, bool) {
     debug!("struct_llfields: {:#?}", layout);
     let field_count = layout.fields.count();
 
     let mut packed = false;
     let mut offset = Size::ZERO;
     let mut prev_align = layout.align;
-    let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
+    let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
     for i in layout.fields.index_by_increasing_offset() {
         let field = layout.field(cx, i);
         packed |= layout.align.abi() < field.align.abi();
@@ -201,12 +201,12 @@ pub struct PointeeInfo {
 pub trait LayoutLlvmExt<'tcx> {
     fn is_llvm_immediate(&self) -> bool;
     fn is_llvm_scalar_pair<'a>(&self) -> bool;
-    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
-    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                               scalar: &layout::Scalar, offset: Size) -> Type;
+                               scalar: &layout::Scalar, offset: Size) -> &'a Type;
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize, immediate: bool) -> Type;
+                                         index: usize, immediate: bool) -> &'a Type;
     fn llvm_field_index(&self, index: usize) -> u64;
     fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
                            -> Option<PointeeInfo>;
@@ -244,7 +244,7 @@ fn is_llvm_scalar_pair<'a>(&self) -> bool {
     /// with the inner-most trailing unsized field using the "minimal unit"
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
-    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             // Use a different cache for scalars because pointers to DSTs
             // can be either fat or thin (data pointers of fat pointers).
@@ -304,7 +304,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
 
         cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty);
 
-        if let Some((mut llty, layout)) = defer {
+        if let Some((llty, layout)) = defer {
             let (llfields, packed) = struct_llfields(cx, layout);
             llty.set_struct_body(&llfields, packed)
         }
@@ -312,7 +312,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         llty
     }
 
-    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             if scalar.is_bool() {
                 return Type::i1(cx);
@@ -322,7 +322,7 @@ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
     }
 
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                               scalar: &layout::Scalar, offset: Size) -> Type {
+                               scalar: &layout::Scalar, offset: Size) -> &'a Type {
         match scalar.value {
             layout::Int(i, _) => Type::from_integer(cx, i),
             layout::Float(FloatTy::F32) => Type::f32(cx),
@@ -340,7 +340,7 @@ fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
     }
 
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize, immediate: bool) -> Type {
+                                         index: usize, immediate: bool) -> &'a Type {
         // HACK(eddyb) special-case fat pointers until LLVM removes
         // pointee types, to avoid bitcasting every `OperandRef::deref`.
         match self.ty.sty {
index 287ad87caacf94e6398c9e6bc8e1ebd9abb063e7..3328948c2951e5ce18e8b500b4ce9e1189c7f6a9 100644 (file)
@@ -8,17 +8,32 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+pub use llvm::Value;
+
 use llvm;
 
 use std::fmt;
+use std::hash::{Hash, Hasher};
+
+impl PartialEq for Value {
+    fn eq(&self, other: &Self) -> bool {
+        self as *const _ == other as *const _
+    }
+}
+
+impl Eq for Value {}
+
+impl Hash for Value {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        (self as *const Self).hash(hasher);
+    }
+}
 
-#[derive(Copy, Clone, PartialEq)]
-pub struct Value(pub llvm::ValueRef);
 
 impl fmt::Debug for Value {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
-            llvm::LLVMRustWriteValueToString(self.0, s);
+            llvm::LLVMRustWriteValueToString(self, s);
         }).expect("nun-UTF8 value description from LLVM"))
     }
 }
index 30f533285ddfdc809e3f54a7a323a8120541578e..a1f4a323f849ee3feecf5ec2f11526aee2bdb6b3 100644 (file)
@@ -20,3 +20,4 @@ rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_incremental = { path = "../librustc_incremental" }
+rustc_metadata_utils = { path = "../librustc_metadata_utils" }
index 3f230dd5d451b5545f241a6d8a9d5ce3ce0a69e5..ae8f65303a7fec7b95cc4b869ea67e1c8d7b53b6 100644 (file)
@@ -114,10 +114,9 @@ impl CodegenBackend for MetadataOnlyCodegenBackend {
     fn init(&self, sess: &Session) {
         for cty in sess.opts.crate_types.iter() {
             match *cty {
-                CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
-                CrateType::CrateTypeExecutable => {},
+                CrateType::Rlib | CrateType::Dylib | CrateType::Executable => {},
                 _ => {
-                    sess.parse_sess.span_diagnostic.warn(
+                    sess.diagnostic().warn(
                         &format!("LLVM unsupported, so output type {} is not supported", cty)
                     );
                 },
@@ -201,13 +200,14 @@ fn join_codegen_and_link(
         let ongoing_codegen = ongoing_codegen.downcast::<OngoingCodegen>()
             .expect("Expected MetadataOnlyCodegenBackend's OngoingCodegen, found Box<dyn Any>");
         for &crate_type in sess.opts.crate_types.iter() {
-            if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
+            if crate_type != CrateType::Rlib &&
+               crate_type != CrateType::Dylib {
                 continue;
             }
             let output_name =
                 out_filename(sess, crate_type, &outputs, &ongoing_codegen.crate_name.as_str());
             let mut compressed = ongoing_codegen.metadata_version.clone();
-            let metadata = if crate_type == CrateType::CrateTypeDylib {
+            let metadata = if crate_type == CrateType::Dylib {
                 DeflateEncoder::new(&mut compressed, Compression::fast())
                     .write_all(&ongoing_codegen.metadata.raw_data)
                     .unwrap();
@@ -220,8 +220,8 @@ fn join_codegen_and_link(
         }
 
         sess.abort_if_errors();
-        if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
-            && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib)
+        if !sess.opts.crate_types.contains(&CrateType::Rlib)
+            && !sess.opts.crate_types.contains(&CrateType::Dylib)
         {
             sess.fatal("Executables are not supported by the metadata-only backend.");
         }
index f59cf5832fcb4eb7a423364ca8d9059626332c0e..3ff2388beea2ad55af1bbf216c3c513dcc777eee 100644 (file)
@@ -37,6 +37,7 @@
 extern crate syntax;
 extern crate syntax_pos;
 #[macro_use] extern crate rustc_data_structures;
+extern crate rustc_metadata_utils;
 
 use rustc::ty::TyCtxt;
 
index aabe931d79c579af326fa6a93ef1263fa72a898f..73cffdf7d491d297667881481aa2129657426738 100644 (file)
 
 use rustc::session::config::{self, OutputFilenames, Input, OutputType};
 use rustc::session::Session;
-use rustc::middle::cstore::{self, LinkMeta};
+use rustc::middle::cstore::LinkMeta;
 use rustc::hir::svh::Svh;
 use std::path::{Path, PathBuf};
 use syntax::{ast, attr};
 use syntax_pos::Span;
+use rustc_metadata_utils::validate_crate_name;
 
 pub fn out_filename(sess: &Session,
                 crate_type: config::CrateType,
@@ -61,7 +62,7 @@ pub fn find_crate_name(sess: Option<&Session>,
                        attrs: &[ast::Attribute],
                        input: &Input) -> String {
     let validate = |s: String, span: Option<Span>| {
-        cstore::validate_crate_name(sess, &s, span);
+        validate_crate_name(sess, &s, span);
         s
     };
 
@@ -113,24 +114,24 @@ pub fn filename_for_input(sess: &Session,
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
 
     match crate_type {
-        config::CrateTypeRlib => {
+        config::CrateType::Rlib => {
             outputs.out_directory.join(&format!("lib{}.rlib", libname))
         }
-        config::CrateTypeCdylib |
-        config::CrateTypeProcMacro |
-        config::CrateTypeDylib => {
+        config::CrateType::Cdylib |
+        config::CrateType::ProcMacro |
+        config::CrateType::Dylib => {
             let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
                                     &sess.target.target.options.dll_suffix);
             outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
                                                 suffix))
         }
-        config::CrateTypeStaticlib => {
+        config::CrateType::Staticlib => {
             let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix,
                                     &sess.target.target.options.staticlib_suffix);
             outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
                                                 suffix))
         }
-        config::CrateTypeExecutable => {
+        config::CrateType::Executable => {
             let suffix = &sess.target.target.options.exe_suffix;
             let out_filename = outputs.path(OutputType::Exe);
             if suffix.is_empty() {
@@ -147,15 +148,15 @@ pub fn filename_for_input(sess: &Session,
 /// Default crate type is used when crate type isn't provided neither
 /// through cmd line arguments nor through crate attributes
 ///
-/// It is CrateTypeExecutable for all platforms but iOS as there is no
+/// It is CrateType::Executable for all platforms but iOS as there is no
 /// way to run iOS binaries anyway without jailbreaking and
 /// interaction with Rust code through static library is the only
 /// option for now
 pub fn default_output_for_target(sess: &Session) -> config::CrateType {
     if !sess.target.target.options.executables {
-        config::CrateTypeStaticlib
+        config::CrateType::Staticlib
     } else {
-        config::CrateTypeExecutable
+        config::CrateType::Executable
     }
 }
 
@@ -163,9 +164,9 @@ pub fn default_output_for_target(sess: &Session) -> config::CrateType {
 pub fn invalid_output_for_target(sess: &Session,
                                  crate_type: config::CrateType) -> bool {
     match crate_type {
-        config::CrateTypeCdylib |
-        config::CrateTypeDylib |
-        config::CrateTypeProcMacro => {
+        config::CrateType::Cdylib |
+        config::CrateType::Dylib |
+        config::CrateType::ProcMacro => {
             if !sess.target.target.options.dynamic_linking {
                 return true
             }
@@ -177,12 +178,12 @@ pub fn invalid_output_for_target(sess: &Session,
     }
     if sess.target.target.options.only_cdylib {
         match crate_type {
-            config::CrateTypeProcMacro | config::CrateTypeDylib => return true,
+            config::CrateType::ProcMacro | config::CrateType::Dylib => return true,
             _ => {}
         }
     }
     if !sess.target.target.options.executables {
-        if crate_type == config::CrateTypeExecutable {
+        if crate_type == config::CrateType::Executable {
             return true
         }
     }
index ac71ecff96457b59e579ab0e7606360dd2b222bf..d834a6502b280fa8f9f4b391df546ccbf532f35a 100644 (file)
@@ -201,7 +201,7 @@ fn get_symbol_hash<'a, 'tcx>(
 
         if avoid_cross_crate_conflicts {
             let instantiating_crate = if is_generic {
-                if !def_id.is_local() && tcx.share_generics() {
+                if !def_id.is_local() && tcx.sess.opts.share_generics() {
                     // If we are re-using a monomorphization from another crate,
                     // we have to compute the symbol hash accordingly.
                     let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id);
index 04d6cb5e2a6d24ce87f57bdc0ac309fe42cd63e6..6e8a45d034250e2d4f7b195aa45c11d564c1561d 100644 (file)
@@ -9,24 +9,74 @@
 // except according to those terms.
 
 use indexed_vec::{Idx, IndexVec};
-use std::iter::FromIterator;
 use std::marker::PhantomData;
 
 type Word = u128;
 const WORD_BITS: usize = 128;
 
-/// A very simple BitVector type.
+/// A very simple BitArray type.
+///
+/// It does not support resizing after creation; use `BitVector` for that.
 #[derive(Clone, Debug, PartialEq)]
-pub struct BitVector<C: Idx> {
+pub struct BitArray<C: Idx> {
     data: Vec<Word>,
     marker: PhantomData<C>,
 }
 
+#[derive(Clone, Debug, PartialEq)]
+pub struct BitVector<C: Idx> {
+    data: BitArray<C>,
+}
+
 impl<C: Idx> BitVector<C> {
+    pub fn grow(&mut self, num_bits: C) {
+        self.data.grow(num_bits)
+    }
+
+    pub fn new() -> BitVector<C> {
+        BitVector {
+            data: BitArray::new(0),
+        }
+    }
+
+    pub fn with_capacity(bits: usize) -> BitVector<C> {
+        BitVector {
+            data: BitArray::new(bits),
+        }
+    }
+
+    /// Returns true if the bit has changed.
+    #[inline]
+    pub fn insert(&mut self, bit: C) -> bool {
+        self.grow(bit);
+        self.data.insert(bit)
+    }
+
     #[inline]
-    pub fn new(num_bits: usize) -> BitVector<C> {
+    pub fn contains(&self, bit: C) -> bool {
+        let (word, mask) = word_mask(bit);
+        if let Some(word) = self.data.data.get(word) {
+            (word & mask) != 0
+        } else {
+            false
+        }
+    }
+}
+
+impl<C: Idx> BitArray<C> {
+    // Do not make this method public, instead switch your use case to BitVector.
+    #[inline]
+    fn grow(&mut self, num_bits: C) {
         let num_words = words(num_bits);
-        BitVector {
+        if self.data.len() <= num_words {
+            self.data.resize(num_words + 1, 0)
+        }
+    }
+
+    #[inline]
+    pub fn new(num_bits: usize) -> BitArray<C> {
+        let num_words = words(num_bits);
+        BitArray {
             data: vec![0; num_words],
             marker: PhantomData,
         }
@@ -54,7 +104,7 @@ pub fn contains(&self, bit: C) -> bool {
     ///
     /// The two vectors must have the same length.
     #[inline]
-    pub fn contains_all(&self, other: &BitVector<C>) -> bool {
+    pub fn contains_all(&self, other: &BitArray<C>) -> bool {
         assert_eq!(self.data.len(), other.data.len());
         self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b)
     }
@@ -94,7 +144,7 @@ pub fn remove(&mut self, bit: C) -> bool {
     }
 
     #[inline]
-    pub fn merge(&mut self, all: &BitVector<C>) -> bool {
+    pub fn merge(&mut self, all: &BitArray<C>) -> bool {
         assert!(self.data.len() == all.data.len());
         let mut changed = false;
         for (i, j) in self.data.iter_mut().zip(&all.data) {
@@ -107,18 +157,10 @@ pub fn merge(&mut self, all: &BitVector<C>) -> bool {
         changed
     }
 
-    #[inline]
-    pub fn grow(&mut self, num_bits: C) {
-        let num_words = words(num_bits);
-        if self.data.len() < num_words {
-            self.data.resize(num_words, 0)
-        }
-    }
-
     /// Iterates over indexes of set bits in a sorted order
     #[inline]
-    pub fn iter<'a>(&'a self) -> BitVectorIter<'a, C> {
-        BitVectorIter {
+    pub fn iter<'a>(&'a self) -> BitIter<'a, C> {
+        BitIter {
             iter: self.data.iter(),
             current: 0,
             idx: 0,
@@ -127,14 +169,14 @@ pub fn iter<'a>(&'a self) -> BitVectorIter<'a, C> {
     }
 }
 
-pub struct BitVectorIter<'a, C: Idx> {
+pub struct BitIter<'a, C: Idx> {
     iter: ::std::slice::Iter<'a, Word>,
     current: Word,
     idx: usize,
     marker: PhantomData<C>
 }
 
-impl<'a, C: Idx> Iterator for BitVectorIter<'a, C> {
+impl<'a, C: Idx> Iterator for BitIter<'a, C> {
     type Item = C;
     fn next(&mut self) -> Option<C> {
         while self.current == 0 {
@@ -163,30 +205,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
-impl<C: Idx> FromIterator<bool> for BitVector<C> {
-    fn from_iter<I>(iter: I) -> BitVector<C>
-    where
-        I: IntoIterator<Item = bool>,
-    {
-        let iter = iter.into_iter();
-        let (len, _) = iter.size_hint();
-        // Make the minimum length for the bitvector WORD_BITS bits since that's
-        // the smallest non-zero size anyway.
-        let len = if len < WORD_BITS { WORD_BITS } else { len };
-        let mut bv = BitVector::new(len);
-        for (idx, val) in iter.enumerate() {
-            if idx > len {
-                bv.grow(C::new(idx));
-            }
-            if val {
-                bv.insert(C::new(idx));
-            }
-        }
-
-        bv
-    }
-}
-
 /// A "bit matrix" is basically a matrix of booleans represented as
 /// one gigantic bitvector. In other words, it is as if you have
 /// `rows` bitvectors, each of length `columns`.
@@ -288,9 +306,9 @@ pub fn merge(&mut self, read: R, write: R) -> bool {
 
     /// Iterates through all the columns set to true in a given row of
     /// the matrix.
-    pub fn iter<'a>(&'a self, row: R) -> BitVectorIter<'a, C> {
+    pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
         let (start, end) = self.range(row);
-        BitVectorIter {
+        BitIter {
             iter: self.vector[start..end].iter(),
             current: 0,
             idx: 0,
@@ -308,7 +326,7 @@ pub struct SparseBitMatrix<R, C>
     C: Idx,
 {
     columns: usize,
-    vector: IndexVec<R, BitVector<C>>,
+    vector: IndexVec<R, BitArray<C>>,
 }
 
 impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
@@ -323,7 +341,7 @@ pub fn new(columns: usize) -> Self {
     fn ensure_row(&mut self, row: R) {
         let columns = self.columns;
         self.vector
-            .ensure_contains_elem(row, || BitVector::new(columns));
+            .ensure_contains_elem(row, || BitArray::new(columns));
     }
 
     /// Sets the cell at `(row, column)` to true. Put another way, insert
@@ -361,7 +379,7 @@ pub fn merge(&mut self, read: R, write: R) -> bool {
     }
 
     /// Merge a row, `from`, into the `into` row.
-    pub fn merge_into(&mut self, into: R, from: &BitVector<C>) -> bool {
+    pub fn merge_into(&mut self, into: R, from: &BitArray<C>) -> bool {
         self.ensure_row(into);
         self.vector[into].merge(from)
     }
@@ -388,11 +406,11 @@ pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
     }
 
     /// Iterates through each row and the accompanying bit set.
-    pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a BitVector<C>)> + 'a {
+    pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a BitArray<C>)> + 'a {
         self.vector.iter_enumerated()
     }
 
-    pub fn row(&self, row: R) -> Option<&BitVector<C>> {
+    pub fn row(&self, row: R) -> Option<&BitArray<C>> {
         self.vector.get(row)
     }
 }
@@ -412,7 +430,7 @@ fn word_mask<C: Idx>(index: C) -> (usize, Word) {
 
 #[test]
 fn bitvec_iter_works() {
-    let mut bitvec: BitVector<usize> = BitVector::new(100);
+    let mut bitvec: BitArray<usize> = BitArray::new(100);
     bitvec.insert(1);
     bitvec.insert(10);
     bitvec.insert(19);
@@ -430,7 +448,7 @@ fn bitvec_iter_works() {
 
 #[test]
 fn bitvec_iter_works_2() {
-    let mut bitvec: BitVector<usize> = BitVector::new(319);
+    let mut bitvec: BitArray<usize> = BitArray::new(319);
     bitvec.insert(0);
     bitvec.insert(127);
     bitvec.insert(191);
@@ -441,8 +459,8 @@ fn bitvec_iter_works_2() {
 
 #[test]
 fn union_two_vecs() {
-    let mut vec1: BitVector<usize> = BitVector::new(65);
-    let mut vec2: BitVector<usize> = BitVector::new(65);
+    let mut vec1: BitArray<usize> = BitArray::new(65);
+    let mut vec2: BitArray<usize> = BitArray::new(65);
     assert!(vec1.insert(3));
     assert!(!vec1.insert(3));
     assert!(vec2.insert(5));
@@ -458,7 +476,7 @@ fn union_two_vecs() {
 
 #[test]
 fn grow() {
-    let mut vec1: BitVector<usize> = BitVector::new(65);
+    let mut vec1: BitVector<usize> = BitVector::with_capacity(65);
     for index in 0..65 {
         assert!(vec1.insert(index));
         assert!(!vec1.insert(index));
index dbfc09116bbaa281bbe5c076ecc21bdf7422c80f..cf9403db658f4fa9fcb5a6dcb4cec900de1b5b76 100644 (file)
@@ -30,7 +30,7 @@
 //! the field `next_edge`). Each of those fields is an array that should
 //! be indexed by the direction (see the type `Direction`).
 
-use bitvec::BitVector;
+use bitvec::BitArray;
 use std::fmt::Debug;
 use std::usize;
 use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
@@ -266,7 +266,7 @@ pub fn nodes_in_postorder<'a>(
         direction: Direction,
         entry_node: NodeIndex,
     ) -> Vec<NodeIndex> {
-        let mut visited = BitVector::new(self.len_nodes());
+        let mut visited = BitArray::new(self.len_nodes());
         let mut stack = vec![];
         let mut result = Vec::with_capacity(self.len_nodes());
         let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
@@ -348,7 +348,7 @@ pub struct DepthFirstTraversal<'g, N, E>
 {
     graph: &'g Graph<N, E>,
     stack: Vec<NodeIndex>,
-    visited: BitVector<usize>,
+    visited: BitArray<usize>,
     direction: Direction,
 }
 
@@ -358,7 +358,7 @@ pub fn with_start_node(
         start_node: NodeIndex,
         direction: Direction,
     ) -> Self {
-        let mut visited = BitVector::new(graph.len_nodes());
+        let mut visited = BitArray::new(graph.len_nodes());
         visited.insert(start_node.node_id());
         DepthFirstTraversal {
             graph,
index 4a72ab57fcc0812fd3c8b3f7395ca3f51afc89e2..76b01beb4bad3dbcd524fb2c07bee6ccb210f434 100644 (file)
@@ -171,8 +171,9 @@ impl<A: Array> Extend<A::Element> for SmallVec<A> {
     fn extend<I: IntoIterator<Item=A::Element>>(&mut self, iter: I) {
         let iter = iter.into_iter();
         self.reserve(iter.size_hint().0);
-        for el in iter {
-            self.push(el);
+        match self.0 {
+            AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
+            _ => iter.for_each(|el| self.push(el))
         }
     }
 }
@@ -213,3 +214,119 @@ fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
         })
     }
 }
+
+#[cfg(test)]
+mod tests {
+    extern crate test;
+    use self::test::Bencher;
+
+    use super::*;
+
+    #[bench]
+    fn fill_small_vec_1_10_with_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(10);
+
+            sv.extend(0..10);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_1_10_wo_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
+
+            sv.extend(0..10);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_8_10_with_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(10);
+
+            sv.extend(0..10);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_8_10_wo_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
+
+            sv.extend(0..10);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_32_10_with_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(10);
+
+            sv.extend(0..10);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_32_10_wo_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
+
+            sv.extend(0..10);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_1_50_with_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(50);
+
+            sv.extend(0..50);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_1_50_wo_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
+
+            sv.extend(0..50);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_8_50_with_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(50);
+
+            sv.extend(0..50);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_8_50_wo_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
+
+            sv.extend(0..50);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_32_50_with_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(50);
+
+            sv.extend(0..50);
+        })
+    }
+
+    #[bench]
+    fn fill_small_vec_32_50_wo_cap(b: &mut Bencher) {
+        b.iter(|| {
+            let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
+
+            sv.extend(0..50);
+        })
+    }
+}
index 5b1b2aadec5638d433168f2de54a7d0083a889b6..c12fc22baf02021db2514a854d0f79e731b1b3cd 100644 (file)
@@ -50,44 +50,22 @@ pub fn new_single(data: T) -> TinyList<T> {
 
     #[inline]
     pub fn insert(&mut self, data: T) {
-        let current_head = mem::replace(&mut self.head, None);
-
-        if let Some(current_head) = current_head {
-            let current_head = Box::new(current_head);
-            self.head = Some(Element {
-                data,
-                next: Some(current_head)
-            });
-        } else {
-            self.head = Some(Element {
-                data,
-                next: None,
-            })
-        }
+        self.head = Some(Element {
+            data,
+            next: mem::replace(&mut self.head, None).map(Box::new),
+        });
     }
 
     #[inline]
     pub fn remove(&mut self, data: &T) -> bool {
-        let remove_head = if let Some(ref mut head) = self.head {
-            if head.data == *data {
-                Some(mem::replace(&mut head.next, None))
-            } else {
-                None
+        self.head = match self.head {
+            Some(ref mut head) if head.data == *data => {
+                mem::replace(&mut head.next, None).map(|x| *x)
             }
-        } else {
-            return false
+            Some(ref mut head) => return head.remove_next(data),
+            None => return false,
         };
-
-        if let Some(remove_head) = remove_head {
-            if let Some(next) = remove_head {
-                self.head = Some(*next);
-            } else {
-                self.head = None;
-            }
-            return true
-        }
-
-        self.head.as_mut().unwrap().remove_next(data)
+        true
     }
 
     #[inline]
@@ -156,6 +134,8 @@ fn contains(&self, data: &T) -> bool {
 #[cfg(test)]
 mod test {
     use super::*;
+    extern crate test;
+    use self::test::Bencher;
 
     #[test]
     fn test_contains_and_insert() {
@@ -248,4 +228,41 @@ fn test_remove_single() {
 
         assert_eq!(list.len(), 0);
     }
+
+    #[bench]
+    fn bench_insert_empty(b: &mut Bencher) {
+        b.iter(|| {
+            let mut list = TinyList::new();
+            list.insert(1);
+        })
+    }
+
+    #[bench]
+    fn bench_insert_one(b: &mut Bencher) {
+        b.iter(|| {
+            let mut list = TinyList::new_single(0);
+            list.insert(1);
+        })
+    }
+
+    #[bench]
+    fn bench_remove_empty(b: &mut Bencher) {
+        b.iter(|| {
+            TinyList::new().remove(&1)
+        });
+    }
+
+    #[bench]
+    fn bench_remove_unknown(b: &mut Bencher) {
+        b.iter(|| {
+            TinyList::new_single(0).remove(&1)
+        });
+    }
+
+    #[bench]
+    fn bench_remove_one(b: &mut Bencher) {
+        b.iter(|| {
+            TinyList::new_single(1).remove(&1)
+        });
+    }
 }
index 24a2354775cb55299822f048e1bc421d6ed7c7cd..805a5ecd9913010a0ad68830b81c83f3a41cdc4d 100644 (file)
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
 use rustc::middle::{self, reachable, resolve_lifetime, stability};
-use rustc::middle::cstore::CrateStoreDyn;
 use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
 use rustc::traits;
 use rustc::util::common::{install_panic_hook, time, ErrorReported};
+use rustc::util::profiling::ProfileCategory;
 use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
 use rustc_incremental;
@@ -352,6 +352,14 @@ macro_rules! controller_entry_point {
         sess.print_perf_stats();
     }
 
+    if sess.opts.debugging_opts.self_profile {
+        sess.print_profiler_results();
+
+        if sess.opts.debugging_opts.profile_json {
+            sess.save_json_results();
+        }
+    }
+
     controller_entry_point!(
         compilation_done,
         sess,
@@ -475,7 +483,7 @@ fn late_callback(
         codegen_backend: &dyn (::CodegenBackend),
         matches: &::getopts::Matches,
         sess: &Session,
-        cstore: &dyn (::CrateStore),
+        cstore: &CStore,
         input: &Input,
         odir: &Option<PathBuf>,
         ofile: &Option<PathBuf>,
@@ -667,6 +675,7 @@ pub fn phase_1_parse_input<'a>(
         profile::begin(sess);
     }
 
+    sess.profiler(|p| p.start_activity(ProfileCategory::Parsing));
     let krate = time(sess, "parsing", || match *input {
         Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess),
         Input::Str {
@@ -674,6 +683,7 @@ pub fn phase_1_parse_input<'a>(
             ref name,
         } => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess),
     })?;
+    sess.profiler(|p| p.end_activity(ProfileCategory::Parsing));
 
     sess.diagnostic().set_continue_after_error(true);
 
@@ -717,9 +727,9 @@ pub struct ExpansionResult {
     pub hir_forest: hir_map::Forest,
 }
 
-pub struct InnerExpansionResult<'a> {
+pub struct InnerExpansionResult<'a, 'b: 'a> {
     pub expanded_crate: ast::Crate,
-    pub resolver: Resolver<'a>,
+    pub resolver: Resolver<'a, 'b>,
     pub hir_forest: hir_map::Forest,
 }
 
@@ -795,7 +805,7 @@ pub fn phase_2_configure_and_expand<F>(
 
 /// Same as phase_2_configure_and_expand, but doesn't let you keep the resolver
 /// around
-pub fn phase_2_configure_and_expand_inner<'a, F>(
+pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>(
     sess: &'a Session,
     cstore: &'a CStore,
     mut krate: ast::Crate,
@@ -804,9 +814,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
     addl_plugins: Option<Vec<String>>,
     make_glob_map: MakeGlobMap,
     resolver_arenas: &'a ResolverArenas<'a>,
-    crate_loader: &'a mut CrateLoader,
+    crate_loader: &'a mut CrateLoader<'b>,
     after_expand: F,
-) -> Result<InnerExpansionResult<'a>, CompileIncomplete>
+) -> Result<InnerExpansionResult<'a, 'b>, CompileIncomplete>
 where
     F: FnOnce(&ast::Crate) -> CompileResult,
 {
@@ -944,6 +954,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
     syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote);
 
     // Expand all macros
+    sess.profiler(|p| p.start_activity(ProfileCategory::Expansion));
     krate = time(sess, "expansion", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
         // dependencies. It's up to us to tell the system where to find all the
@@ -1021,6 +1032,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
         }
         krate
     });
+    sess.profiler(|p| p.end_activity(ProfileCategory::Expansion));
 
     krate = time(sess, "maybe building test harness", || {
         syntax::test::modify_for_testing(
@@ -1046,7 +1058,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
         krate = time(sess, "maybe creating a macro crate", || {
             let crate_types = sess.crate_types.borrow();
             let num_crate_types = crate_types.len();
-            let is_proc_macro_crate = crate_types.contains(&config::CrateTypeProcMacro);
+            let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro);
             let is_test_crate = sess.opts.test;
             syntax_ext::proc_macro_registrar::modify(
                 &sess.parse_sess,
@@ -1121,7 +1133,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
     // Unresolved macros might be due to mistyped `#[macro_use]`,
     // so abort after checking for unknown attributes. (#49074)
     if resolver.found_unresolved_macro {
-        sess.parse_sess.span_diagnostic.abort_if_errors();
+        sess.diagnostic().abort_if_errors();
     }
 
     // Lower ast -> hir.
@@ -1196,7 +1208,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(
     codegen_backend: &dyn CodegenBackend,
     control: &CompileController,
     sess: &'tcx Session,
-    cstore: &'tcx CrateStoreDyn,
+    cstore: &'tcx CStore,
     hir_map: hir_map::Map<'tcx>,
     mut analysis: ty::CrateAnalysis,
     resolutions: Resolutions,
@@ -1350,7 +1362,9 @@ pub fn phase_4_codegen<'a, 'tcx>(
         ::rustc::middle::dependency_format::calculate(tcx)
     });
 
+    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
     let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx));
+    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
     if tcx.sess.profile_queries() {
         profile::dump(&tcx.sess, "profile_queries".to_string())
     }
@@ -1487,13 +1501,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
         .filter_map(|a| {
             if a.check_name("crate_type") {
                 match a.value_str() {
-                    Some(ref n) if *n == "rlib" => Some(config::CrateTypeRlib),
-                    Some(ref n) if *n == "dylib" => Some(config::CrateTypeDylib),
-                    Some(ref n) if *n == "cdylib" => Some(config::CrateTypeCdylib),
+                    Some(ref n) if *n == "rlib" => Some(config::CrateType::Rlib),
+                    Some(ref n) if *n == "dylib" => Some(config::CrateType::Dylib),
+                    Some(ref n) if *n == "cdylib" => Some(config::CrateType::Cdylib),
                     Some(ref n) if *n == "lib" => Some(config::default_lib_output()),
-                    Some(ref n) if *n == "staticlib" => Some(config::CrateTypeStaticlib),
-                    Some(ref n) if *n == "proc-macro" => Some(config::CrateTypeProcMacro),
-                    Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable),
+                    Some(ref n) if *n == "staticlib" => Some(config::CrateType::Staticlib),
+                    Some(ref n) if *n == "proc-macro" => Some(config::CrateType::ProcMacro),
+                    Some(ref n) if *n == "bin" => Some(config::CrateType::Executable),
                     Some(_) => {
                         session.buffer_lint(
                             lint::builtin::UNKNOWN_CRATE_TYPES,
@@ -1520,7 +1534,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
     // If we're generating a test executable, then ignore all other output
     // styles at all other locations
     if session.opts.test {
-        return vec![config::CrateTypeExecutable];
+        return vec![config::CrateType::Executable];
     }
 
     // Only check command line flags if present. If no types are specified by
@@ -1584,7 +1598,7 @@ pub fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
     let is_exe = session
         .crate_types
         .borrow()
-        .contains(&config::CrateTypeExecutable);
+        .contains(&config::CrateType::Executable);
     hasher.write(if is_exe { b"exe" } else { b"lib" });
 
     CrateDisambiguator::from(hasher.finish())
index 44fac8ae0a09aab4915f61d101d38e30057b8d7f..556ee9f5716ea32c9849b8f33af0af4e39573edc 100644 (file)
@@ -79,7 +79,6 @@
 use rustc::session::{early_error, early_warn};
 use rustc::lint::Lint;
 use rustc::lint;
-use rustc::middle::cstore::CrateStore;
 use rustc_metadata::locator;
 use rustc_metadata::cstore::CStore;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
@@ -677,7 +676,7 @@ fn late_callback(&mut self,
                      _: &dyn CodegenBackend,
                      _: &getopts::Matches,
                      _: &Session,
-                     _: &dyn CrateStore,
+                     _: &CStore,
                      _: &Input,
                      _: &Option<PathBuf>,
                      _: &Option<PathBuf>)
@@ -885,7 +884,7 @@ fn late_callback(&mut self,
                      codegen_backend: &dyn CodegenBackend,
                      matches: &getopts::Matches,
                      sess: &Session,
-                     cstore: &dyn CrateStore,
+                     cstore: &CStore,
                      input: &Input,
                      odir: &Option<PathBuf>,
                      ofile: &Option<PathBuf>)
@@ -991,7 +990,7 @@ pub fn enable_save_analysis(control: &mut CompileController) {
 
 impl RustcDefaultCalls {
     pub fn list_metadata(sess: &Session,
-                         cstore: &dyn CrateStore,
+                         cstore: &CStore,
                          matches: &getopts::Matches,
                          input: &Input)
                          -> Compilation {
@@ -1003,7 +1002,7 @@ pub fn list_metadata(sess: &Session,
                     let mut v = Vec::new();
                     locator::list_file_metadata(&sess.target.target,
                                                 path,
-                                                cstore.metadata_loader(),
+                                                &*cstore.metadata_loader,
                                                 &mut v)
                             .unwrap();
                     println!("{}", String::from_utf8(v).unwrap());
index 9135c9e179fcaebb4f505414922b28632bf5c7e1..3e74aef9e7345791beaab0480a387e509843d3f2 100644 (file)
 use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
 use rustc::cfg;
 use rustc::cfg::graphviz::LabelledCFG;
-use rustc::middle::cstore::CrateStoreDyn;
 use rustc::session::Session;
 use rustc::session::config::{Input, OutputFilenames};
 use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
+use rustc_metadata::cstore::CStore;
 
 use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
 
@@ -200,7 +200,7 @@ fn call_with_pp_support<'tcx, A, F>(&self,
     }
     fn call_with_pp_support_hir<'tcx, A, F>(&self,
                                                sess: &'tcx Session,
-                                               cstore: &'tcx CrateStoreDyn,
+                                               cstore: &'tcx CStore,
                                                hir_map: &hir_map::Map<'tcx>,
                                                analysis: &ty::CrateAnalysis,
                                                resolutions: &Resolutions,
@@ -972,7 +972,7 @@ pub fn print_after_parsing(sess: &Session,
 }
 
 pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
-                                                cstore: &'tcx CrateStoreDyn,
+                                                cstore: &'tcx CStore,
                                                 hir_map: &hir_map::Map<'tcx>,
                                                 analysis: &ty::CrateAnalysis,
                                                 resolutions: &Resolutions,
@@ -1128,7 +1128,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
 // with a different callback than the standard driver, so that isn't easy.
 // Instead, we call that function ourselves.
 fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
-                                       cstore: &'a CrateStoreDyn,
+                                       cstore: &'a CStore,
                                        hir_map: &hir_map::Map<'tcx>,
                                        analysis: &ty::CrateAnalysis,
                                        resolutions: &Resolutions,
index 5b2092ea9eb11fe17cdbdec653ef540d819b4e58..03651322bc9806ae7dceacd35ca0aa2bb4bdc771 100644 (file)
@@ -99,7 +99,7 @@ fn test_env<F>(source_string: &str,
     where F: FnOnce(Env)
 {
     syntax::with_globals(|| {
-        let mut options = config::basic_options();
+        let mut options = config::Options::default();
         options.debugging_opts.verbose = true;
         options.unstable_features = UnstableFeatures::Allow;
 
index a0f3abda077f94720015a1053c7b57a582788a1f..1b34898b99084e20f6ddf15b46080f1666d3d8fe 100644 (file)
@@ -26,6 +26,7 @@
 pub struct DiagnosticBuilder<'a> {
     pub handler: &'a Handler,
     diagnostic: Diagnostic,
+    allow_suggestions: bool,
 }
 
 /// In general, the `DiagnosticBuilder` uses deref to allow access to
@@ -186,27 +187,67 @@ pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self
                                      msg: &str,
                                      suggestions: Vec<String>)
                                      -> &mut Self);
-    forward!(pub fn span_suggestion_with_applicability(&mut self,
-                                                sp: Span,
-                                                msg: &str,
-                                                suggestion: String,
-                                                applicability: Applicability)
-                                                -> &mut Self);
-    forward!(pub fn span_suggestions_with_applicability(&mut self,
-                                                 sp: Span,
-                                                 msg: &str,
-                                                 suggestions: Vec<String>,
-                                                 applicability: Applicability)
-                                                 -> &mut Self);
-    forward!(pub fn span_suggestion_short_with_applicability(&mut self,
-                                                             sp: Span,
-                                                             msg: &str,
-                                                             suggestion: String,
-                                                             applicability: Applicability)
-                                                             -> &mut Self);
+    pub fn span_suggestion_with_applicability(&mut self,
+                                              sp: Span,
+                                              msg: &str,
+                                              suggestion: String,
+                                              applicability: Applicability)
+                                              -> &mut Self {
+        if !self.allow_suggestions {
+            return self
+        }
+        self.diagnostic.span_suggestion_with_applicability(
+            sp,
+            msg,
+            suggestion,
+            applicability,
+        );
+        self
+    }
+
+    pub fn span_suggestions_with_applicability(&mut self,
+                                               sp: Span,
+                                               msg: &str,
+                                               suggestions: Vec<String>,
+                                               applicability: Applicability)
+                                               -> &mut Self {
+        if !self.allow_suggestions {
+            return self
+        }
+        self.diagnostic.span_suggestions_with_applicability(
+            sp,
+            msg,
+            suggestions,
+            applicability,
+        );
+        self
+    }
+
+    pub fn span_suggestion_short_with_applicability(&mut self,
+                                                    sp: Span,
+                                                    msg: &str,
+                                                    suggestion: String,
+                                                    applicability: Applicability)
+                                                    -> &mut Self {
+        if !self.allow_suggestions {
+            return self
+        }
+        self.diagnostic.span_suggestion_short_with_applicability(
+            sp,
+            msg,
+            suggestion,
+            applicability,
+        );
+        self
+    }
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
     forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
 
+    pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self {
+        self.allow_suggestions = allow;
+        self
+    }
+
     /// Convenience function for internal use, clients should use one of the
     /// struct_* methods on Handler.
     pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
@@ -228,7 +269,11 @@ pub fn new_with_code(handler: &'a Handler,
     /// diagnostic.
     pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
                          -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder { handler, diagnostic }
+        DiagnosticBuilder {
+            handler,
+            diagnostic,
+            allow_suggestions: true,
+        }
     }
 }
 
index 561f5fbf5c41e5a809f59257b5ebdf93626b4fa4..4ef4397d974c420254d2b3b465690a56a298d285 100644 (file)
@@ -84,7 +84,12 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                         let msg = "denote infinite loops with `loop { ... }`";
                         let condition_span = cx.tcx.sess.codemap().def_span(e.span);
                         let mut err = cx.struct_span_lint(WHILE_TRUE, condition_span, msg);
-                        err.span_suggestion_short(condition_span, "use `loop`", "loop".to_owned());
+                        err.span_suggestion_short_with_applicability(
+                            condition_span,
+                            "use `loop`",
+                            "loop".to_owned(),
+                            Applicability::MachineApplicable
+                        );
                         err.emit();
                     }
                 }
@@ -191,7 +196,12 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
                                      fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant", ident));
                         let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':');
-                        err.span_suggestion_short(subspan, "remove this", ident.to_string());
+                        err.span_suggestion_short_with_applicability(
+                            subspan,
+                            "remove this",
+                            ident.to_string(),
+                            Applicability::MachineApplicable
+                        );
                         err.emit();
                     }
                 }
@@ -708,10 +718,11 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
                         | "i8" | "i16" | "i32" | "i64" | "i128" | "isize" => {
                             // if the literal could have been a valid `repr` arg,
                             // suggest the correct syntax
-                            warn.span_suggestion(
+                            warn.span_suggestion_with_applicability(
                                 attr.span,
                                 "give `repr` a hint",
                                 repr_str(&lit.as_str()),
+                                Applicability::MachineApplicable
                             );
                             suggested = true;
                         }
@@ -779,7 +790,12 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
                     let msg = format!("use of deprecated attribute `{}`: {}. See {}",
                                       name, reason, link);
                     let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg);
-                    err.span_suggestion_short(attr.span, "remove this attribute", "".to_owned());
+                    err.span_suggestion_short_with_applicability(
+                        attr.span,
+                        "remove this attribute",
+                        "".to_owned(),
+                        Applicability::MachineApplicable
+                    );
                     err.emit();
                 }
                 return;
@@ -1201,7 +1217,12 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                 }
             };
             if let Some(replacement) = suggestion {
-                err.span_suggestion(vis.span, "try making it public", replacement);
+                err.span_suggestion_with_applicability(
+                    vis.span,
+                    "try making it public",
+                    replacement,
+                    Applicability::MachineApplicable
+                );
             }
         };
 
@@ -1225,9 +1246,14 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                                                                   it.span,
                                                                   "functions generic over \
                                                                    types must be mangled");
-                                err.span_suggestion_short(no_mangle_attr.span,
-                                                          "remove this attribute",
-                                                          "".to_owned());
+                                err.span_suggestion_short_with_applicability(
+                                    no_mangle_attr.span,
+                                    "remove this attribute",
+                                    "".to_owned(),
+                                    // Use of `#[no_mangle]` suggests FFI intent; correct
+                                    // fix may be to monomorphize source by hand
+                                    Applicability::MaybeIncorrect
+                                );
                                 err.emit();
                                 break;
                             }
@@ -1257,9 +1283,12 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                         .unwrap_or(0) as u32;
                     // `const` is 5 chars
                     let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
-                    err.span_suggestion(const_span,
-                                        "try a static value",
-                                        "pub static".to_owned());
+                    err.span_suggestion_with_applicability(
+                        const_span,
+                        "try a static value",
+                        "pub static".to_owned(),
+                        Applicability::MachineApplicable
+                    );
                     err.emit();
                 }
             }
@@ -1630,7 +1659,13 @@ fn validate_const<'a, 'tcx>(
 
 fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
     let def_id = cx.tcx.hir.body_owner_def_id(body_id);
-    let param_env = cx.tcx.param_env(def_id);
+    let is_static = cx.tcx.is_static(def_id).is_some();
+    let param_env = if is_static {
+        // Use the same param_env as `codegen_static_initializer`, to reuse the cache.
+        ty::ParamEnv::reveal_all()
+    } else {
+        cx.tcx.param_env(def_id)
+    };
     let cid = ::rustc::mir::interpret::GlobalId {
         instance: ty::Instance::mono(cx.tcx, def_id),
         promoted: None
@@ -1638,8 +1673,8 @@ fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
     match cx.tcx.const_eval(param_env.and(cid)) {
         Ok(val) => validate_const(cx.tcx, val, param_env, cid, what),
         Err(err) => {
-            // errors for statics are already reported directly in the query
-            if cx.tcx.is_static(def_id).is_none() {
+            // errors for statics are already reported directly in the query, avoid duplicates
+            if !is_static {
                 let span = cx.tcx.def_span(def_id);
                 err.report_as_lint(
                     cx.tcx.at(span),
index 78a8c494f48c53e5d4f09c85199608a5921d6c76..b92ac0ff57bd88478b5fb40c95520c55e884173a 100644 (file)
@@ -45,7 +45,6 @@
 use rustc::lint::builtin::{
     BARE_TRAIT_OBJECTS,
     ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
-    MACRO_USE_EXTERN_CRATE,
     ELIDED_LIFETIMES_IN_PATHS,
     parser::QUESTION_MARK_MACRO_SEP
 };
@@ -195,11 +194,18 @@ macro_rules! add_lint_group {
     add_lint_group!(sess,
                     "rust_2018_idioms",
                     BARE_TRAIT_OBJECTS,
-                    UNREACHABLE_PUB,
                     UNUSED_EXTERN_CRATES,
-                    MACRO_USE_EXTERN_CRATE,
-                    ELIDED_LIFETIMES_IN_PATHS,
-                    ELLIPSIS_INCLUSIVE_RANGE_PATTERNS);
+                    ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
+                    ELIDED_LIFETIMES_IN_PATHS
+
+                    // FIXME(#52665, #47816) not always applicable and not all
+                    // macros are ready for this yet.
+                    // UNREACHABLE_PUB,
+
+                    // FIXME macro crates are not up for this yet, too much
+                    // breakage is seen if we try to encourage this lint.
+                    // MACRO_USE_EXTERN_CRATE,
+                    );
 
     // Guidelines for creating a future incompatibility lint:
     //
index ad4a4fbff649ca5cdd6ea6590ed743e066ba0b82..4dc66fb812144d884476b0d5ef354824caee9ae9 100644 (file)
@@ -22,6 +22,7 @@
 use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 
 use syntax::{ast, attr};
+use syntax::errors::Applicability;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::Span;
 use syntax::codemap;
@@ -143,9 +144,12 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
                                                              OVERFLOWING_LITERALS,
                                                              parent_expr.span,
                                                              "only u8 can be cast into char");
-                                        err.span_suggestion(parent_expr.span,
-                                                            &"use a char literal instead",
-                                                            format!("'\\u{{{:X}}}'", lit_val));
+                                        err.span_suggestion_with_applicability(
+                                            parent_expr.span,
+                                            &"use a char literal instead",
+                                            format!("'\\u{{{:X}}}'", lit_val),
+                                            Applicability::MachineApplicable
+                                        );
                                         err.emit();
                                         return
                                     }
@@ -398,10 +402,11 @@ fn report_bin_hex_error(
             {
                 if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
                     let (sans_suffix, _) = repr_str.split_at(pos);
-                    err.span_suggestion(
+                    err.span_suggestion_with_applicability(
                         expr.span,
                         &format!("consider using `{}` instead", sugg_ty),
                         format!("{}{}", sans_suffix, sugg_ty),
+                        Applicability::MachineApplicable
                     );
                 } else {
                     err.help(&format!("consider using `{}` instead", sugg_ty));
index da291f56ee4e56ce175817dc7f1c42caf02e100f..2b8540ea3861a25761de61597d1cae79f8ebefc6 100644 (file)
@@ -17,6 +17,7 @@
 
 use syntax::ast;
 use syntax::attr;
+use syntax::errors::Applicability;
 use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
 use syntax::print::pprust;
 use syntax::symbol::keywords;
@@ -303,9 +304,12 @@ fn check_unused_parens_core(&self,
                             _ => false,
                         }
                     }).to_owned();
-                err.span_suggestion_short(value.span,
-                                          "remove these parentheses",
-                                          parens_removed);
+                err.span_suggestion_short_with_applicability(
+                    value.span,
+                    "remove these parentheses",
+                    parens_removed,
+                    Applicability::MachineApplicable
+                );
                 err.emit();
             }
         }
index 0978c2ceb141d785b634e278112dc3414b903843..013badb71cc5ab8d1bfe7a965a639e56e3b906f1 100644 (file)
@@ -12,11 +12,6 @@ path = "lib.rs"
 static-libstdcpp = []
 emscripten = []
 
-[dependencies]
-bitflags = "1.0"
-libc = "0.2"
-rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
-
 [build-dependencies]
 build_helper = { path = "../build_helper" }
 cc = "1.0.1"
diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs
deleted file mode 100644 (file)
index 9d86900..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A wrapper around LLVM's archive (.a) code
-
-use ArchiveRef;
-
-use std::ffi::CString;
-use std::marker;
-use std::path::Path;
-use std::slice;
-use std::str;
-
-pub struct ArchiveRO {
-    ptr: ArchiveRef,
-}
-
-unsafe impl Send for ArchiveRO {}
-
-pub struct Iter<'a> {
-    archive: &'a ArchiveRO,
-    ptr: ::ArchiveIteratorRef,
-}
-
-pub struct Child<'a> {
-    ptr: ::ArchiveChildRef,
-    _data: marker::PhantomData<&'a ArchiveRO>,
-}
-
-impl ArchiveRO {
-    /// Opens a static archive for read-only purposes. This is more optimized
-    /// than the `open` method because it uses LLVM's internal `Archive` class
-    /// rather than shelling out to `ar` for everything.
-    ///
-    /// If this archive is used with a mutable method, then an error will be
-    /// raised.
-    pub fn open(dst: &Path) -> Result<ArchiveRO, String> {
-        return unsafe {
-            let s = path2cstr(dst);
-            let ar = ::LLVMRustOpenArchive(s.as_ptr());
-            if ar.is_null() {
-                Err(::last_error().unwrap_or("failed to open archive".to_string()))
-            } else {
-                Ok(ArchiveRO { ptr: ar })
-            }
-        };
-
-        #[cfg(unix)]
-        fn path2cstr(p: &Path) -> CString {
-            use std::os::unix::prelude::*;
-            use std::ffi::OsStr;
-            let p: &OsStr = p.as_ref();
-            CString::new(p.as_bytes()).unwrap()
-        }
-        #[cfg(windows)]
-        fn path2cstr(p: &Path) -> CString {
-            CString::new(p.to_str().unwrap()).unwrap()
-        }
-    }
-
-    pub fn raw(&self) -> ArchiveRef {
-        self.ptr
-    }
-
-    pub fn iter(&self) -> Iter {
-        unsafe {
-            Iter {
-                ptr: ::LLVMRustArchiveIteratorNew(self.ptr),
-                archive: self,
-            }
-        }
-    }
-}
-
-impl Drop for ArchiveRO {
-    fn drop(&mut self) {
-        unsafe {
-            ::LLVMRustDestroyArchive(self.ptr);
-        }
-    }
-}
-
-impl<'a> Iterator for Iter<'a> {
-    type Item = Result<Child<'a>, String>;
-
-    fn next(&mut self) -> Option<Result<Child<'a>, String>> {
-        let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
-        if ptr.is_null() {
-            ::last_error().map(Err)
-        } else {
-            Some(Ok(Child {
-                ptr,
-                _data: marker::PhantomData,
-            }))
-        }
-    }
-}
-
-impl<'a> Drop for Iter<'a> {
-    fn drop(&mut self) {
-        unsafe {
-            ::LLVMRustArchiveIteratorFree(self.ptr);
-        }
-    }
-}
-
-impl<'a> Child<'a> {
-    pub fn name(&self) -> Option<&'a str> {
-        unsafe {
-            let mut name_len = 0;
-            let name_ptr = ::LLVMRustArchiveChildName(self.ptr, &mut name_len);
-            if name_ptr.is_null() {
-                None
-            } else {
-                let name = slice::from_raw_parts(name_ptr as *const u8, name_len as usize);
-                str::from_utf8(name).ok().map(|s| s.trim())
-            }
-        }
-    }
-
-    pub fn data(&self) -> &'a [u8] {
-        unsafe {
-            let mut data_len = 0;
-            let data_ptr = ::LLVMRustArchiveChildData(self.ptr, &mut data_len);
-            if data_ptr.is_null() {
-                panic!("failed to read data from archive child");
-            }
-            slice::from_raw_parts(data_ptr as *const u8, data_len as usize)
-        }
-    }
-
-    pub fn raw(&self) -> ::ArchiveChildRef {
-        self.ptr
-    }
-}
-
-impl<'a> Drop for Child<'a> {
-    fn drop(&mut self) {
-        unsafe {
-            ::LLVMRustArchiveChildFree(self.ptr);
-        }
-    }
-}
index 1619637b827dfe99a1bad79271fa3a6f6c318fa2..4e24a26983d48754a9a84dd78cb2d1b083f18866 100644 (file)
@@ -100,6 +100,10 @@ fn main() {
         optional_components.push("hexagon");
     }
 
+    if major > 6 {
+        optional_components.push("riscv");
+    }
+
     // FIXME: surely we don't need all these components, right? Stuff like mcjit
     //        or interpreter the compiler itself never uses.
     let required_components = &["ipo",
@@ -271,5 +275,6 @@ fn main() {
     if target.contains("windows-gnu") {
         println!("cargo:rustc-link-lib=static-nobundle=gcc_s");
         println!("cargo:rustc-link-lib=static-nobundle=pthread");
+        println!("cargo:rustc-link-lib=dylib=uuid");
     }
 }
diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs
deleted file mode 100644 (file)
index e73c570..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! LLVM diagnostic reports.
-
-pub use self::OptimizationDiagnosticKind::*;
-pub use self::Diagnostic::*;
-
-use libc::c_uint;
-use std::ptr;
-
-use {DiagnosticInfoRef, TwineRef, ValueRef};
-
-#[derive(Copy, Clone)]
-pub enum OptimizationDiagnosticKind {
-    OptimizationRemark,
-    OptimizationMissed,
-    OptimizationAnalysis,
-    OptimizationAnalysisFPCommute,
-    OptimizationAnalysisAliasing,
-    OptimizationFailure,
-    OptimizationRemarkOther,
-}
-
-impl OptimizationDiagnosticKind {
-    pub fn describe(self) -> &'static str {
-        match self {
-            OptimizationRemark | OptimizationRemarkOther => "remark",
-            OptimizationMissed => "missed",
-            OptimizationAnalysis => "analysis",
-            OptimizationAnalysisFPCommute => "floating-point",
-            OptimizationAnalysisAliasing => "aliasing",
-            OptimizationFailure => "failure",
-        }
-    }
-}
-
-pub struct OptimizationDiagnostic {
-    pub kind: OptimizationDiagnosticKind,
-    pub pass_name: String,
-    pub function: ValueRef,
-    pub line: c_uint,
-    pub column: c_uint,
-    pub filename: String,
-    pub message: String,
-}
-
-impl OptimizationDiagnostic {
-    unsafe fn unpack(kind: OptimizationDiagnosticKind,
-                     di: DiagnosticInfoRef)
-                     -> OptimizationDiagnostic {
-        let mut function = ptr::null_mut();
-        let mut line = 0;
-        let mut column = 0;
-
-        let mut message = None;
-        let mut filename = None;
-        let pass_name = super::build_string(|pass_name|
-            message = super::build_string(|message|
-                filename = super::build_string(|filename|
-                    super::LLVMRustUnpackOptimizationDiagnostic(di,
-                                                                pass_name,
-                                                                &mut function,
-                                                                &mut line,
-                                                                &mut column,
-                                                                filename,
-                                                                message)
-                )
-            )
-        );
-
-        let mut filename = filename.unwrap_or(String::new());
-        if filename.is_empty() {
-            filename.push_str("<unknown file>");
-        }
-
-        OptimizationDiagnostic {
-            kind,
-            pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
-            function,
-            line,
-            column,
-            filename,
-            message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM")
-        }
-    }
-}
-
-#[derive(Copy, Clone)]
-pub struct InlineAsmDiagnostic {
-    pub cookie: c_uint,
-    pub message: TwineRef,
-    pub instruction: ValueRef,
-}
-
-impl InlineAsmDiagnostic {
-    unsafe fn unpack(di: DiagnosticInfoRef) -> InlineAsmDiagnostic {
-
-        let mut opt = InlineAsmDiagnostic {
-            cookie: 0,
-            message: ptr::null_mut(),
-            instruction: ptr::null_mut(),
-        };
-
-        super::LLVMRustUnpackInlineAsmDiagnostic(di,
-                                                 &mut opt.cookie,
-                                                 &mut opt.message,
-                                                 &mut opt.instruction);
-
-        opt
-    }
-}
-
-pub enum Diagnostic {
-    Optimization(OptimizationDiagnostic),
-    InlineAsm(InlineAsmDiagnostic),
-    PGO(DiagnosticInfoRef),
-
-    /// LLVM has other types that we do not wrap here.
-    UnknownDiagnostic(DiagnosticInfoRef),
-}
-
-impl Diagnostic {
-    pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
-        use super::DiagnosticKind as Dk;
-        let kind = super::LLVMRustGetDiagInfoKind(di);
-
-        match kind {
-            Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
-
-            Dk::OptimizationRemark => {
-                Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
-            }
-            Dk::OptimizationRemarkOther => {
-                Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
-            }
-            Dk::OptimizationRemarkMissed => {
-                Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
-            }
-
-            Dk::OptimizationRemarkAnalysis => {
-                Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
-            }
-
-            Dk::OptimizationRemarkAnalysisFPCommute => {
-                Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
-            }
-
-            Dk::OptimizationRemarkAnalysisAliasing => {
-                Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
-            }
-
-            Dk::OptimizationFailure => {
-                Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
-            }
-
-            Dk::PGOProfile => {
-                PGO(di)
-            }
-
-            _ => UnknownDiagnostic(di),
-        }
-    }
-}
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
deleted file mode 100644 (file)
index 8d04438..0000000
+++ /dev/null
@@ -1,1800 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression'
-// once support for LLVM 3.9 is dropped.
-//
-// This method was changed in this LLVM patch:
-// https://reviews.llvm.org/D26769
-
-use debuginfo::{DIBuilderRef, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
-                DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
-                DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
-                DINameSpace, DIFlags};
-
-use libc::{c_uint, c_int, size_t, c_char};
-use libc::{c_longlong, c_ulonglong, c_void};
-
-use RustStringRef;
-
-pub type Opcode = u32;
-pub type Bool = c_uint;
-
-pub const True: Bool = 1 as Bool;
-pub const False: Bool = 0 as Bool;
-
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum LLVMRustResult {
-    Success,
-    Failure,
-}
-// Consts for the LLVM CallConv type, pre-cast to usize.
-
-/// LLVM CallingConv::ID. Should we wrap this?
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum CallConv {
-    CCallConv = 0,
-    FastCallConv = 8,
-    ColdCallConv = 9,
-    X86StdcallCallConv = 64,
-    X86FastcallCallConv = 65,
-    ArmAapcsCallConv = 67,
-    Msp430Intr = 69,
-    X86_ThisCall = 70,
-    PtxKernel = 71,
-    X86_64_SysV = 78,
-    X86_64_Win64 = 79,
-    X86_VectorCall = 80,
-    X86_Intr = 83,
-    AmdGpuKernel = 91,
-}
-
-/// LLVMRustLinkage
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-#[repr(C)]
-pub enum Linkage {
-    ExternalLinkage = 0,
-    AvailableExternallyLinkage = 1,
-    LinkOnceAnyLinkage = 2,
-    LinkOnceODRLinkage = 3,
-    WeakAnyLinkage = 4,
-    WeakODRLinkage = 5,
-    AppendingLinkage = 6,
-    InternalLinkage = 7,
-    PrivateLinkage = 8,
-    ExternalWeakLinkage = 9,
-    CommonLinkage = 10,
-}
-
-// LLVMRustVisibility
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-#[repr(C)]
-pub enum Visibility {
-    Default = 0,
-    Hidden = 1,
-    Protected = 2,
-}
-
-/// LLVMDiagnosticSeverity
-#[derive(Copy, Clone, Debug)]
-#[repr(C)]
-pub enum DiagnosticSeverity {
-    Error = 0,
-    Warning = 1,
-    Remark = 2,
-    Note = 3,
-}
-
-/// LLVMDLLStorageClass
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum DLLStorageClass {
-    Default = 0,
-    DllImport = 1, // Function to be imported from DLL.
-    DllExport = 2, // Function to be accessible from DLL.
-}
-
-/// Matches LLVMRustAttribute in rustllvm.h
-/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
-/// though it is not ABI compatible (since it's a C++ enum)
-#[repr(C)]
-#[derive(Copy, Clone, Debug)]
-pub enum Attribute {
-    AlwaysInline    = 0,
-    ByVal           = 1,
-    Cold            = 2,
-    InlineHint      = 3,
-    MinSize         = 4,
-    Naked           = 5,
-    NoAlias         = 6,
-    NoCapture       = 7,
-    NoInline        = 8,
-    NonNull         = 9,
-    NoRedZone       = 10,
-    NoReturn        = 11,
-    NoUnwind        = 12,
-    OptimizeForSize = 13,
-    ReadOnly        = 14,
-    SExt            = 15,
-    StructRet       = 16,
-    UWTable         = 17,
-    ZExt            = 18,
-    InReg           = 19,
-    SanitizeThread  = 20,
-    SanitizeAddress = 21,
-    SanitizeMemory  = 22,
-}
-
-/// LLVMIntPredicate
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum IntPredicate {
-    IntEQ = 32,
-    IntNE = 33,
-    IntUGT = 34,
-    IntUGE = 35,
-    IntULT = 36,
-    IntULE = 37,
-    IntSGT = 38,
-    IntSGE = 39,
-    IntSLT = 40,
-    IntSLE = 41,
-}
-
-/// LLVMRealPredicate
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum RealPredicate {
-    RealPredicateFalse = 0,
-    RealOEQ = 1,
-    RealOGT = 2,
-    RealOGE = 3,
-    RealOLT = 4,
-    RealOLE = 5,
-    RealONE = 6,
-    RealORD = 7,
-    RealUNO = 8,
-    RealUEQ = 9,
-    RealUGT = 10,
-    RealUGE = 11,
-    RealULT = 12,
-    RealULE = 13,
-    RealUNE = 14,
-    RealPredicateTrue = 15,
-}
-
-/// LLVMTypeKind
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum TypeKind {
-    Void = 0,
-    Half = 1,
-    Float = 2,
-    Double = 3,
-    X86_FP80 = 4,
-    FP128 = 5,
-    PPC_FP128 = 6,
-    Label = 7,
-    Integer = 8,
-    Function = 9,
-    Struct = 10,
-    Array = 11,
-    Pointer = 12,
-    Vector = 13,
-    Metadata = 14,
-    X86_MMX = 15,
-    Token = 16,
-}
-
-/// LLVMAtomicRmwBinOp
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum AtomicRmwBinOp {
-    AtomicXchg = 0,
-    AtomicAdd = 1,
-    AtomicSub = 2,
-    AtomicAnd = 3,
-    AtomicNand = 4,
-    AtomicOr = 5,
-    AtomicXor = 6,
-    AtomicMax = 7,
-    AtomicMin = 8,
-    AtomicUMax = 9,
-    AtomicUMin = 10,
-}
-
-/// LLVMAtomicOrdering
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum AtomicOrdering {
-    NotAtomic = 0,
-    Unordered = 1,
-    Monotonic = 2,
-    // Consume = 3,  // Not specified yet.
-    Acquire = 4,
-    Release = 5,
-    AcquireRelease = 6,
-    SequentiallyConsistent = 7,
-}
-
-/// LLVMRustSynchronizationScope
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum SynchronizationScope {
-    Other,
-    SingleThread,
-    CrossThread,
-}
-
-/// LLVMRustFileType
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum FileType {
-    Other,
-    AssemblyFile,
-    ObjectFile,
-}
-
-/// LLVMMetadataType
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum MetadataType {
-    MD_dbg = 0,
-    MD_tbaa = 1,
-    MD_prof = 2,
-    MD_fpmath = 3,
-    MD_range = 4,
-    MD_tbaa_struct = 5,
-    MD_invariant_load = 6,
-    MD_alias_scope = 7,
-    MD_noalias = 8,
-    MD_nontemporal = 9,
-    MD_mem_parallel_loop_access = 10,
-    MD_nonnull = 11,
-}
-
-/// LLVMRustAsmDialect
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum AsmDialect {
-    Other,
-    Att,
-    Intel,
-}
-
-/// LLVMRustCodeGenOptLevel
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum CodeGenOptLevel {
-    Other,
-    None,
-    Less,
-    Default,
-    Aggressive,
-}
-
-/// LLVMRelocMode
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum RelocMode {
-    Default,
-    Static,
-    PIC,
-    DynamicNoPic,
-    ROPI,
-    RWPI,
-    ROPI_RWPI,
-}
-
-/// LLVMRustCodeModel
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum CodeModel {
-    Other,
-    Small,
-    Kernel,
-    Medium,
-    Large,
-    None,
-}
-
-/// LLVMRustDiagnosticKind
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum DiagnosticKind {
-    Other,
-    InlineAsm,
-    StackSize,
-    DebugMetadataVersion,
-    SampleProfile,
-    OptimizationRemark,
-    OptimizationRemarkMissed,
-    OptimizationRemarkAnalysis,
-    OptimizationRemarkAnalysisFPCommute,
-    OptimizationRemarkAnalysisAliasing,
-    OptimizationRemarkOther,
-    OptimizationFailure,
-    PGOProfile,
-}
-
-/// LLVMRustArchiveKind
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum ArchiveKind {
-    Other,
-    K_GNU,
-    K_BSD,
-    K_COFF,
-}
-
-/// LLVMRustPassKind
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[repr(C)]
-pub enum PassKind {
-    Other,
-    Function,
-    Module,
-}
-
-/// LLVMRustThinLTOData
-pub enum ThinLTOData {}
-
-/// LLVMRustThinLTOBuffer
-pub enum ThinLTOBuffer {}
-
-/// LLVMRustThinLTOModule
-#[repr(C)]
-pub struct ThinLTOModule {
-    pub identifier: *const c_char,
-    pub data: *const u8,
-    pub len: usize,
-}
-
-/// LLVMThreadLocalMode
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum ThreadLocalMode {
-  NotThreadLocal,
-  GeneralDynamic,
-  LocalDynamic,
-  InitialExec,
-  LocalExec
-}
-
-// Opaque pointer types
-#[allow(missing_copy_implementations)]
-pub enum Module_opaque {}
-pub type ModuleRef = *mut Module_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Context_opaque {}
-pub type ContextRef = *mut Context_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Type_opaque {}
-pub type TypeRef = *mut Type_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Value_opaque {}
-pub type ValueRef = *mut Value_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Metadata_opaque {}
-pub type MetadataRef = *mut Metadata_opaque;
-#[allow(missing_copy_implementations)]
-pub enum BasicBlock_opaque {}
-pub type BasicBlockRef = *mut BasicBlock_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Builder_opaque {}
-pub type BuilderRef = *mut Builder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ExecutionEngine_opaque {}
-pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum MemoryBuffer_opaque {}
-pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManager_opaque {}
-pub type PassManagerRef = *mut PassManager_opaque;
-#[allow(missing_copy_implementations)]
-pub enum PassManagerBuilder_opaque {}
-pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Use_opaque {}
-pub type UseRef = *mut Use_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetData_opaque {}
-pub type TargetDataRef = *mut TargetData_opaque;
-#[allow(missing_copy_implementations)]
-pub enum ObjectFile_opaque {}
-pub type ObjectFileRef = *mut ObjectFile_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SectionIterator_opaque {}
-pub type SectionIteratorRef = *mut SectionIterator_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Pass_opaque {}
-pub type PassRef = *mut Pass_opaque;
-#[allow(missing_copy_implementations)]
-pub enum TargetMachine_opaque {}
-pub type TargetMachineRef = *mut TargetMachine_opaque;
-pub enum Archive_opaque {}
-pub type ArchiveRef = *mut Archive_opaque;
-pub enum ArchiveIterator_opaque {}
-pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
-pub enum ArchiveChild_opaque {}
-pub type ArchiveChildRef = *mut ArchiveChild_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Twine_opaque {}
-pub type TwineRef = *mut Twine_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DiagnosticInfo_opaque {}
-pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
-#[allow(missing_copy_implementations)]
-pub enum DebugLoc_opaque {}
-pub type DebugLocRef = *mut DebugLoc_opaque;
-#[allow(missing_copy_implementations)]
-pub enum SMDiagnostic_opaque {}
-pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
-#[allow(missing_copy_implementations)]
-pub enum RustArchiveMember_opaque {}
-pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
-#[allow(missing_copy_implementations)]
-pub enum OperandBundleDef_opaque {}
-pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;
-#[allow(missing_copy_implementations)]
-pub enum Linker_opaque {}
-pub type LinkerRef = *mut Linker_opaque;
-
-pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
-pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
-
-
-pub mod debuginfo {
-    use super::MetadataRef;
-
-    #[allow(missing_copy_implementations)]
-    pub enum DIBuilder_opaque {}
-    pub type DIBuilderRef = *mut DIBuilder_opaque;
-
-    pub type DIDescriptor = MetadataRef;
-    pub type DIScope = DIDescriptor;
-    pub type DILocation = DIDescriptor;
-    pub type DIFile = DIScope;
-    pub type DILexicalBlock = DIScope;
-    pub type DISubprogram = DIScope;
-    pub type DINameSpace = DIScope;
-    pub type DIType = DIDescriptor;
-    pub type DIBasicType = DIType;
-    pub type DIDerivedType = DIType;
-    pub type DICompositeType = DIDerivedType;
-    pub type DIVariable = DIDescriptor;
-    pub type DIGlobalVariable = DIDescriptor;
-    pub type DIArray = DIDescriptor;
-    pub type DISubrange = DIDescriptor;
-    pub type DIEnumerator = DIDescriptor;
-    pub type DITemplateTypeParameter = DIDescriptor;
-
-    // These values **must** match with LLVMRustDIFlags!!
-    bitflags! {
-        #[repr(C)]
-        #[derive(Default)]
-        pub struct DIFlags: ::libc::uint32_t {
-            const FlagZero                = 0;
-            const FlagPrivate             = 1;
-            const FlagProtected           = 2;
-            const FlagPublic              = 3;
-            const FlagFwdDecl             = (1 << 2);
-            const FlagAppleBlock          = (1 << 3);
-            const FlagBlockByrefStruct    = (1 << 4);
-            const FlagVirtual             = (1 << 5);
-            const FlagArtificial          = (1 << 6);
-            const FlagExplicit            = (1 << 7);
-            const FlagPrototyped          = (1 << 8);
-            const FlagObjcClassComplete   = (1 << 9);
-            const FlagObjectPointer       = (1 << 10);
-            const FlagVector              = (1 << 11);
-            const FlagStaticMember        = (1 << 12);
-            const FlagLValueReference     = (1 << 13);
-            const FlagRValueReference     = (1 << 14);
-            const FlagExternalTypeRef     = (1 << 15);
-            const FlagIntroducedVirtual   = (1 << 18);
-            const FlagBitField            = (1 << 19);
-            const FlagNoReturn            = (1 << 20);
-            const FlagMainSubprogram      = (1 << 21);
-        }
-    }
-}
-
-pub enum ModuleBuffer {}
-
-// This annotation is primarily needed for MSVC where attributes like
-// dllimport/dllexport are applied and need to be correct for everything to
-// link successfully. The #[link] annotation here says "these symbols are
-// included statically" which means that they're all exported with dllexport
-// and from the rustc_llvm dynamic library. Otherwise the rustc_codegen_llvm dynamic
-// library would not be able to access these symbols.
-#[link(name = "rustllvm", kind = "static")]
-extern "C" {
-    // Create and destroy contexts.
-    pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef;
-    pub fn LLVMContextDispose(C: ContextRef);
-    pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint;
-
-    // Create and destroy modules.
-    pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: ContextRef) -> ModuleRef;
-    pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
-    pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
-    pub fn LLVMDisposeModule(M: ModuleRef);
-
-    /// Data layout. See Module::getDataLayout.
-    pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
-    pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
-
-    /// See Module::dump.
-    pub fn LLVMDumpModule(M: ModuleRef);
-
-    /// See Module::setModuleInlineAsm.
-    pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
-    pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
-
-    /// See llvm::LLVMTypeKind::getTypeID.
-    pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
-
-    // Operations on integer types
-    pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef;
-
-    pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
-
-    // Operations on real types
-    pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
-
-    // Operations on function types
-    pub fn LLVMFunctionType(ReturnType: TypeRef,
-                            ParamTypes: *const TypeRef,
-                            ParamCount: c_uint,
-                            IsVarArg: Bool)
-                            -> TypeRef;
-    pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
-    pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
-    pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef);
-
-    // Operations on struct types
-    pub fn LLVMStructTypeInContext(C: ContextRef,
-                                   ElementTypes: *const TypeRef,
-                                   ElementCount: c_uint,
-                                   Packed: Bool)
-                                   -> TypeRef;
-    pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
-
-    // Operations on array, pointer, and vector types (sequence types)
-    pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef;
-    pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint) -> TypeRef;
-    pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef;
-
-    pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
-    pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
-
-    // Operations on other types
-    pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMX86MMXTypeInContext(C: ContextRef) -> TypeRef;
-    pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef;
-
-    // Operations on all values
-    pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
-    pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char;
-    pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char);
-    pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
-    pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
-
-    // Operations on Uses
-    pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
-    pub fn LLVMGetNextUse(U: UseRef) -> UseRef;
-    pub fn LLVMGetUser(U: UseRef) -> ValueRef;
-
-    // Operations on Users
-    pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
-
-    // Operations on constants of any type
-    pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef;
-    pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef;
-    pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
-
-    // Operations on metadata
-    pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef;
-    pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef;
-    pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef);
-
-    // Operations on scalar constants
-    pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef;
-    pub fn LLVMConstIntOfArbitraryPrecision(IntTy: TypeRef, Wn: c_uint, Ws: *const u64) -> ValueRef;
-    pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
-    pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
-    pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
-                                  high: *mut u64, low: *mut u64) -> bool;
-    pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64;
-
-
-    // Operations on composite constants
-    pub fn LLVMConstStringInContext(C: ContextRef,
-                                    Str: *const c_char,
-                                    Length: c_uint,
-                                    DontNullTerminate: Bool)
-                                    -> ValueRef;
-    pub fn LLVMConstStructInContext(C: ContextRef,
-                                    ConstantVals: *const ValueRef,
-                                    Count: c_uint,
-                                    Packed: Bool)
-                                    -> ValueRef;
-
-    pub fn LLVMConstArray(ElementTy: TypeRef,
-                          ConstantVals: *const ValueRef,
-                          Length: c_uint)
-                          -> ValueRef;
-    pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint) -> ValueRef;
-
-    // Constant expressions
-    pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
-    pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
-    pub fn LLVMConstGEP(
-        ConstantVal: ValueRef,
-        ConstantIndices: *const ValueRef,
-        NumIndices: c_uint,
-    ) -> ValueRef;
-    pub fn LLVMConstInBoundsGEP(
-        ConstantVal: ValueRef,
-        ConstantIndices: *const ValueRef,
-        NumIndices: c_uint,
-    ) -> ValueRef;
-    pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef, isSigned: Bool) -> ValueRef;
-    pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
-    pub fn LLVMConstExtractValue(AggConstant: ValueRef,
-                                 IdxList: *const c_uint,
-                                 NumIdx: c_uint)
-                                 -> ValueRef;
-    pub fn LLVMConstInlineAsm(Ty: TypeRef,
-                              AsmString: *const c_char,
-                              Constraints: *const c_char,
-                              HasSideEffects: Bool,
-                              IsAlignStack: Bool)
-                              -> ValueRef;
-
-
-    // Operations on global variables, functions, and aliases (globals)
-    pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
-    pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
-    pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage;
-    pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage);
-    pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
-    pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
-    pub fn LLVMRustGetVisibility(Global: ValueRef) -> Visibility;
-    pub fn LLVMRustSetVisibility(Global: ValueRef, Viz: Visibility);
-    pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
-    pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
-    pub fn LLVMSetDLLStorageClass(V: ValueRef, C: DLLStorageClass);
-
-
-    // Operations on global variables
-    pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef;
-    pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMDeleteGlobal(GlobalVar: ValueRef);
-    pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
-    pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef);
-    pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
-    pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode);
-    pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
-    pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
-    pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
-
-    // Operations on functions
-    pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef;
-    pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
-    pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
-    pub fn LLVMRustGetOrInsertFunction(M: ModuleRef,
-                                       Name: *const c_char,
-                                       FunctionTy: TypeRef)
-                                       -> ValueRef;
-    pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
-    pub fn LLVMRustAddAlignmentAttr(Fn: ValueRef, index: c_uint, bytes: u32);
-    pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64);
-    pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: ValueRef, index: c_uint, bytes: u64);
-    pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: Attribute);
-    pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef,
-                                              index: c_uint,
-                                              Name: *const c_char,
-                                              Value: *const c_char);
-    pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: Attribute);
-
-    // Operations on parameters
-    pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
-    pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
-
-    // Operations on basic blocks
-    pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMAppendBasicBlockInContext(C: ContextRef,
-                                         Fn: ValueRef,
-                                         Name: *const c_char)
-                                         -> BasicBlockRef;
-    pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
-
-    // Operations on instructions
-    pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
-    pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMInstructionEraseFromParent(Inst: ValueRef);
-
-    // Operations on call sites
-    pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
-    pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, attr: Attribute);
-    pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u32);
-    pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u64);
-    pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: ValueRef,
-                                                        index: c_uint,
-                                                        bytes: u64);
-
-    // Operations on load/store instructions (only)
-    pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool);
-
-    // Operations on phi nodes
-    pub fn LLVMAddIncoming(PhiNode: ValueRef,
-                           IncomingValues: *const ValueRef,
-                           IncomingBlocks: *const BasicBlockRef,
-                           Count: c_uint);
-
-    // Instruction builders
-    pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
-    pub fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef);
-    pub fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef);
-    pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef);
-    pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
-    pub fn LLVMDisposeBuilder(Builder: BuilderRef);
-
-    // Metadata
-    pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
-    pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
-    pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
-
-    // Terminators
-    pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
-    pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
-    pub fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *const ValueRef, N: c_uint) -> ValueRef;
-    pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
-    pub fn LLVMBuildCondBr(B: BuilderRef,
-                           If: ValueRef,
-                           Then: BasicBlockRef,
-                           Else: BasicBlockRef)
-                           -> ValueRef;
-    pub fn LLVMBuildSwitch(B: BuilderRef,
-                           V: ValueRef,
-                           Else: BasicBlockRef,
-                           NumCases: c_uint)
-                           -> ValueRef;
-    pub fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef, NumDests: c_uint) -> ValueRef;
-    pub fn LLVMRustBuildInvoke(B: BuilderRef,
-                               Fn: ValueRef,
-                               Args: *const ValueRef,
-                               NumArgs: c_uint,
-                               Then: BasicBlockRef,
-                               Catch: BasicBlockRef,
-                               Bundle: OperandBundleDefRef,
-                               Name: *const c_char)
-                               -> ValueRef;
-    pub fn LLVMBuildLandingPad(B: BuilderRef,
-                               Ty: TypeRef,
-                               PersFn: ValueRef,
-                               NumClauses: c_uint,
-                               Name: *const c_char)
-                               -> ValueRef;
-    pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
-    pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
-
-    pub fn LLVMRustBuildCleanupPad(B: BuilderRef,
-                                   ParentPad: ValueRef,
-                                   ArgCnt: c_uint,
-                                   Args: *const ValueRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMRustBuildCleanupRet(B: BuilderRef,
-                                   CleanupPad: ValueRef,
-                                   UnwindBB: BasicBlockRef)
-                                   -> ValueRef;
-    pub fn LLVMRustBuildCatchPad(B: BuilderRef,
-                                 ParentPad: ValueRef,
-                                 ArgCnt: c_uint,
-                                 Args: *const ValueRef,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMRustBuildCatchRet(B: BuilderRef, Pad: ValueRef, BB: BasicBlockRef) -> ValueRef;
-    pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef,
-                                    ParentPad: ValueRef,
-                                    BB: BasicBlockRef,
-                                    NumHandlers: c_uint,
-                                    Name: *const c_char)
-                                    -> ValueRef;
-    pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef);
-    pub fn LLVMSetPersonalityFn(Func: ValueRef, Pers: ValueRef);
-
-    // Add a case to the switch instruction
-    pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef);
-
-    // Add a clause to the landing pad instruction
-    pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
-
-    // Set the cleanup on a landing pad instruction
-    pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
-
-    // Arithmetic
-    pub fn LLVMBuildAdd(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWAdd(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWAdd(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFAdd(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSub(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWSub(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWSub(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFSub(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildMul(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildNSWMul(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildNUWMul(B: BuilderRef,
-                           LHS: ValueRef,
-                           RHS: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFMul(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildUDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildExactUDiv(B: BuilderRef,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildSDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildExactSDiv(B: BuilderRef,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildFDiv(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildURem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSRem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFRem(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildShl(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildLShr(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildAShr(B: BuilderRef,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildAnd(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildOr(B: BuilderRef,
-                       LHS: ValueRef,
-                       RHS: ValueRef,
-                       Name: *const c_char)
-                       -> ValueRef;
-    pub fn LLVMBuildXor(B: BuilderRef,
-                        LHS: ValueRef,
-                        RHS: ValueRef,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildBinOp(B: BuilderRef,
-                          Op: Opcode,
-                          LHS: ValueRef,
-                          RHS: ValueRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef);
-
-    // Memory
-    pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
-    pub fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, Name: *const c_char) -> ValueRef;
-
-    pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) -> ValueRef;
-
-    pub fn LLVMBuildGEP(B: BuilderRef,
-                        Pointer: ValueRef,
-                        Indices: *const ValueRef,
-                        NumIndices: c_uint,
-                        Name: *const c_char)
-                        -> ValueRef;
-    pub fn LLVMBuildInBoundsGEP(B: BuilderRef,
-                                Pointer: ValueRef,
-                                Indices: *const ValueRef,
-                                NumIndices: c_uint,
-                                Name: *const c_char)
-                                -> ValueRef;
-    pub fn LLVMBuildStructGEP(B: BuilderRef,
-                              Pointer: ValueRef,
-                              Idx: c_uint,
-                              Name: *const c_char)
-                              -> ValueRef;
-    pub fn LLVMBuildGlobalString(B: BuilderRef,
-                                 Str: *const c_char,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMBuildGlobalStringPtr(B: BuilderRef,
-                                    Str: *const c_char,
-                                    Name: *const c_char)
-                                    -> ValueRef;
-
-    // Casts
-    pub fn LLVMBuildTrunc(B: BuilderRef,
-                          Val: ValueRef,
-                          DestTy: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildZExt(B: BuilderRef,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildSExt(B: BuilderRef,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFPToUI(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFPToSI(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildUIToFP(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildSIToFP(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildFPTrunc(B: BuilderRef,
-                            Val: ValueRef,
-                            DestTy: TypeRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-    pub fn LLVMBuildFPExt(B: BuilderRef,
-                          Val: ValueRef,
-                          DestTy: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildPtrToInt(B: BuilderRef,
-                             Val: ValueRef,
-                             DestTy: TypeRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildIntToPtr(B: BuilderRef,
-                             Val: ValueRef,
-                             DestTy: TypeRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildBitCast(B: BuilderRef,
-                            Val: ValueRef,
-                            DestTy: TypeRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-    pub fn LLVMBuildZExtOrBitCast(B: BuilderRef,
-                                  Val: ValueRef,
-                                  DestTy: TypeRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildSExtOrBitCast(B: BuilderRef,
-                                  Val: ValueRef,
-                                  DestTy: TypeRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildTruncOrBitCast(B: BuilderRef,
-                                   Val: ValueRef,
-                                   DestTy: TypeRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMBuildCast(B: BuilderRef,
-                         Op: Opcode,
-                         Val: ValueRef,
-                         DestTy: TypeRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildPointerCast(B: BuilderRef,
-                                Val: ValueRef,
-                                DestTy: TypeRef,
-                                Name: *const c_char)
-                                -> ValueRef;
-    pub fn LLVMRustBuildIntCast(B: BuilderRef,
-                                Val: ValueRef,
-                                DestTy: TypeRef,
-                                IsSized: bool)
-                                -> ValueRef;
-    pub fn LLVMBuildFPCast(B: BuilderRef,
-                           Val: ValueRef,
-                           DestTy: TypeRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-
-    // Comparisons
-    pub fn LLVMBuildICmp(B: BuilderRef,
-                         Op: c_uint,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-    pub fn LLVMBuildFCmp(B: BuilderRef,
-                         Op: c_uint,
-                         LHS: ValueRef,
-                         RHS: ValueRef,
-                         Name: *const c_char)
-                         -> ValueRef;
-
-    // Miscellaneous instructions
-    pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMRustBuildCall(B: BuilderRef,
-                             Fn: ValueRef,
-                             Args: *const ValueRef,
-                             NumArgs: c_uint,
-                             Bundle: OperandBundleDefRef,
-                             Name: *const c_char)
-                             -> ValueRef;
-    pub fn LLVMBuildSelect(B: BuilderRef,
-                           If: ValueRef,
-                           Then: ValueRef,
-                           Else: ValueRef,
-                           Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildVAArg(B: BuilderRef,
-                          list: ValueRef,
-                          Ty: TypeRef,
-                          Name: *const c_char)
-                          -> ValueRef;
-    pub fn LLVMBuildExtractElement(B: BuilderRef,
-                                   VecVal: ValueRef,
-                                   Index: ValueRef,
-                                   Name: *const c_char)
-                                   -> ValueRef;
-    pub fn LLVMBuildInsertElement(B: BuilderRef,
-                                  VecVal: ValueRef,
-                                  EltVal: ValueRef,
-                                  Index: ValueRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildShuffleVector(B: BuilderRef,
-                                  V1: ValueRef,
-                                  V2: ValueRef,
-                                  Mask: ValueRef,
-                                  Name: *const c_char)
-                                  -> ValueRef;
-    pub fn LLVMBuildExtractValue(B: BuilderRef,
-                                 AggVal: ValueRef,
-                                 Index: c_uint,
-                                 Name: *const c_char)
-                                 -> ValueRef;
-    pub fn LLVMBuildInsertValue(B: BuilderRef,
-                                AggVal: ValueRef,
-                                EltVal: ValueRef,
-                                Index: c_uint,
-                                Name: *const c_char)
-                                -> ValueRef;
-
-    pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef,
-                                         Acc: ValueRef,
-                                         Src: ValueRef)
-                                         -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef,
-                                         Acc: ValueRef,
-                                         Src: ValueRef)
-                                         -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef,
-                                       Src: ValueRef)
-                                       -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef,
-                                        Src: ValueRef)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef,
-                                        Src: ValueRef,
-                                        IsSigned: bool)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef,
-                                        Src: ValueRef,
-                                        IsSigned: bool)
-                                        -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef,
-                                         Src: ValueRef,
-                                         IsNaN: bool)
-                                         -> ValueRef;
-    pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef,
-                                         Src: ValueRef,
-                                         IsNaN: bool)
-                                         -> ValueRef;
-
-    pub fn LLVMRustBuildMinNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef;
-    pub fn LLVMRustBuildMaxNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef;
-
-    pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
-    pub fn LLVMBuildPtrDiff(B: BuilderRef,
-                            LHS: ValueRef,
-                            RHS: ValueRef,
-                            Name: *const c_char)
-                            -> ValueRef;
-
-    // Atomic Operations
-    pub fn LLVMRustBuildAtomicLoad(B: BuilderRef,
-                                   PointerVal: ValueRef,
-                                   Name: *const c_char,
-                                   Order: AtomicOrdering)
-                                   -> ValueRef;
-
-    pub fn LLVMRustBuildAtomicStore(B: BuilderRef,
-                                    Val: ValueRef,
-                                    Ptr: ValueRef,
-                                    Order: AtomicOrdering)
-                                    -> ValueRef;
-
-    pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef,
-                                      LHS: ValueRef,
-                                      CMP: ValueRef,
-                                      RHS: ValueRef,
-                                      Order: AtomicOrdering,
-                                      FailureOrder: AtomicOrdering,
-                                      Weak: Bool)
-                                      -> ValueRef;
-
-    pub fn LLVMBuildAtomicRMW(B: BuilderRef,
-                              Op: AtomicRmwBinOp,
-                              LHS: ValueRef,
-                              RHS: ValueRef,
-                              Order: AtomicOrdering,
-                              SingleThreaded: Bool)
-                              -> ValueRef;
-
-    pub fn LLVMRustBuildAtomicFence(B: BuilderRef,
-                                    Order: AtomicOrdering,
-                                    Scope: SynchronizationScope);
-
-
-    // Selected entries from the downcasts.
-    pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
-    pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
-
-    /// Writes a module to the specified path. Returns 0 on success.
-    pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
-
-    /// Creates target data from a target layout string.
-    pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
-
-    /// Disposes target data.
-    pub fn LLVMDisposeTargetData(TD: TargetDataRef);
-
-    /// Creates a pass manager.
-    pub fn LLVMCreatePassManager() -> PassManagerRef;
-
-    /// Creates a function-by-function pass manager
-    pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef) -> PassManagerRef;
-
-    /// Disposes a pass manager.
-    pub fn LLVMDisposePassManager(PM: PassManagerRef);
-
-    /// Runs a pass manager on a module.
-    pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
-
-    pub fn LLVMInitializePasses();
-
-    pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
-    pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
-    pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef, Value: Bool);
-    pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: PassManagerBuilderRef, Value: Bool);
-    pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: PassManagerBuilderRef,
-                                                         threshold: c_uint);
-    pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: PassManagerBuilderRef,
-                                                           PM: PassManagerRef);
-
-    pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: PassManagerBuilderRef,
-                                                             PM: PassManagerRef);
-    pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: PassManagerBuilderRef,
-                                                        PM: PassManagerRef,
-                                                        Internalize: Bool,
-                                                        RunInliner: Bool);
-    pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
-        PMB: PassManagerBuilderRef,
-        PM: PassManagerRef) -> bool;
-
-    // Stuff that's in rustllvm/ because it's not upstream yet.
-
-    /// Opens an object file.
-    pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
-    /// Closes an object file.
-    pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
-
-    /// Enumerates the sections in an object file.
-    pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
-    /// Destroys a section iterator.
-    pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
-    /// Returns true if the section iterator is at the end of the section
-    /// list:
-    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef, SI: SectionIteratorRef) -> Bool;
-    /// Moves the section iterator to point to the next section.
-    pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
-    /// Returns the current section size.
-    pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
-    /// Returns the current section contents as a string buffer.
-    pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
-
-    /// Reads the given file and returns it as a memory buffer. Use
-    /// LLVMDisposeMemoryBuffer() to get rid of it.
-    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char) -> MemoryBufferRef;
-
-    pub fn LLVMStartMultithreaded() -> Bool;
-
-    /// Returns a string describing the last error caused by an LLVMRust* call.
-    pub fn LLVMRustGetLastError() -> *const c_char;
-
-    /// Print the pass timings since static dtors aren't picking them up.
-    pub fn LLVMRustPrintPassTimings();
-
-    pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef;
-
-    pub fn LLVMStructSetBody(StructTy: TypeRef,
-                             ElementTypes: *const TypeRef,
-                             ElementCount: c_uint,
-                             Packed: Bool);
-
-    /// Prepares inline assembly.
-    pub fn LLVMRustInlineAsm(Ty: TypeRef,
-                             AsmString: *const c_char,
-                             Constraints: *const c_char,
-                             SideEffects: Bool,
-                             AlignStack: Bool,
-                             Dialect: AsmDialect)
-                             -> ValueRef;
-
-    pub fn LLVMRustDebugMetadataVersion() -> u32;
-    pub fn LLVMRustVersionMajor() -> u32;
-    pub fn LLVMRustVersionMinor() -> u32;
-
-    pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32);
-
-    pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef;
-
-    pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
-
-    pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef);
-
-    pub fn LLVMRustDIBuilderFinalize(Builder: DIBuilderRef);
-
-    pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
-                                              Lang: c_uint,
-                                              File: DIFile,
-                                              Producer: *const c_char,
-                                              isOptimized: bool,
-                                              Flags: *const c_char,
-                                              RuntimeVer: c_uint,
-                                              SplitName: *const c_char)
-                                              -> DIDescriptor;
-
-    pub fn LLVMRustDIBuilderCreateFile(Builder: DIBuilderRef,
-                                       Filename: *const c_char,
-                                       Directory: *const c_char)
-                                       -> DIFile;
-
-    pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: DIBuilderRef,
-                                                 File: DIFile,
-                                                 ParameterTypes: DIArray)
-                                                 -> DICompositeType;
-
-    pub fn LLVMRustDIBuilderCreateFunction(Builder: DIBuilderRef,
-                                           Scope: DIDescriptor,
-                                           Name: *const c_char,
-                                           LinkageName: *const c_char,
-                                           File: DIFile,
-                                           LineNo: c_uint,
-                                           Ty: DIType,
-                                           isLocalToUnit: bool,
-                                           isDefinition: bool,
-                                           ScopeLine: c_uint,
-                                           Flags: DIFlags,
-                                           isOptimized: bool,
-                                           Fn: ValueRef,
-                                           TParam: DIArray,
-                                           Decl: DIDescriptor)
-                                           -> DISubprogram;
-
-    pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef,
-                                            Name: *const c_char,
-                                            SizeInBits: u64,
-                                            AlignInBits: u32,
-                                            Encoding: c_uint)
-                                            -> DIBasicType;
-
-    pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef,
-                                              PointeeTy: DIType,
-                                              SizeInBits: u64,
-                                              AlignInBits: u32,
-                                              Name: *const c_char)
-                                              -> DIDerivedType;
-
-    pub fn LLVMRustDIBuilderCreateStructType(Builder: DIBuilderRef,
-                                             Scope: DIDescriptor,
-                                             Name: *const c_char,
-                                             File: DIFile,
-                                             LineNumber: c_uint,
-                                             SizeInBits: u64,
-                                             AlignInBits: u32,
-                                             Flags: DIFlags,
-                                             DerivedFrom: DIType,
-                                             Elements: DIArray,
-                                             RunTimeLang: c_uint,
-                                             VTableHolder: DIType,
-                                             UniqueId: *const c_char)
-                                             -> DICompositeType;
-
-    pub fn LLVMRustDIBuilderCreateMemberType(Builder: DIBuilderRef,
-                                             Scope: DIDescriptor,
-                                             Name: *const c_char,
-                                             File: DIFile,
-                                             LineNo: c_uint,
-                                             SizeInBits: u64,
-                                             AlignInBits: u32,
-                                             OffsetInBits: u64,
-                                             Flags: DIFlags,
-                                             Ty: DIType)
-                                             -> DIDerivedType;
-
-    pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: DIBuilderRef,
-                                               Scope: DIScope,
-                                               File: DIFile,
-                                               Line: c_uint,
-                                               Col: c_uint)
-                                               -> DILexicalBlock;
-
-    pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: DIBuilderRef,
-                                                   Scope: DIScope,
-                                                   File: DIFile)
-                                                   -> DILexicalBlock;
-
-    pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
-                                                 Context: DIScope,
-                                                 Name: *const c_char,
-                                                 LinkageName: *const c_char,
-                                                 File: DIFile,
-                                                 LineNo: c_uint,
-                                                 Ty: DIType,
-                                                 isLocalToUnit: bool,
-                                                 Val: ValueRef,
-                                                 Decl: DIDescriptor,
-                                                 AlignInBits: u32)
-                                                 -> DIGlobalVariable;
-
-    pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef,
-                                           Tag: c_uint,
-                                           Scope: DIDescriptor,
-                                           Name: *const c_char,
-                                           File: DIFile,
-                                           LineNo: c_uint,
-                                           Ty: DIType,
-                                           AlwaysPreserve: bool,
-                                           Flags: DIFlags,
-                                           ArgNo: c_uint,
-                                           AlignInBits: u32)
-                                           -> DIVariable;
-
-    pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef,
-                                            Size: u64,
-                                            AlignInBits: u32,
-                                            Ty: DIType,
-                                            Subscripts: DIArray)
-                                            -> DIType;
-
-    pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef,
-                                             Size: u64,
-                                             AlignInBits: u32,
-                                             Ty: DIType,
-                                             Subscripts: DIArray)
-                                             -> DIType;
-
-    pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef,
-                                                Lo: i64,
-                                                Count: i64)
-                                                -> DISubrange;
-
-    pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: DIBuilderRef,
-                                             Ptr: *const DIDescriptor,
-                                             Count: c_uint)
-                                             -> DIArray;
-
-    pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef,
-                                               Val: ValueRef,
-                                               VarInfo: DIVariable,
-                                               AddrOps: *const i64,
-                                               AddrOpsCount: c_uint,
-                                               DL: ValueRef,
-                                               InsertAtEnd: BasicBlockRef)
-                                               -> ValueRef;
-
-    pub fn LLVMRustDIBuilderCreateEnumerator(Builder: DIBuilderRef,
-                                             Name: *const c_char,
-                                             Val: u64)
-                                             -> DIEnumerator;
-
-    pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: DIBuilderRef,
-                                                  Scope: DIScope,
-                                                  Name: *const c_char,
-                                                  File: DIFile,
-                                                  LineNumber: c_uint,
-                                                  SizeInBits: u64,
-                                                  AlignInBits: u32,
-                                                  Elements: DIArray,
-                                                  ClassType: DIType)
-                                                  -> DIType;
-
-    pub fn LLVMRustDIBuilderCreateUnionType(Builder: DIBuilderRef,
-                                            Scope: DIScope,
-                                            Name: *const c_char,
-                                            File: DIFile,
-                                            LineNumber: c_uint,
-                                            SizeInBits: u64,
-                                            AlignInBits: u32,
-                                            Flags: DIFlags,
-                                            Elements: DIArray,
-                                            RunTimeLang: c_uint,
-                                            UniqueId: *const c_char)
-                                            -> DIType;
-
-    pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
-
-    pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
-                                                        Scope: DIScope,
-                                                        Name: *const c_char,
-                                                        Ty: DIType,
-                                                        File: DIFile,
-                                                        LineNo: c_uint,
-                                                        ColumnNo: c_uint)
-                                                        -> DITemplateTypeParameter;
-
-
-    pub fn LLVMRustDIBuilderCreateNameSpace(Builder: DIBuilderRef,
-                                            Scope: DIScope,
-                                            Name: *const c_char,
-                                            File: DIFile,
-                                            LineNo: c_uint)
-                                            -> DINameSpace;
-    pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: DIBuilderRef,
-                                               CompositeType: DIType,
-                                               TypeArray: DIArray);
-
-
-    pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
-                                                Line: c_uint,
-                                                Column: c_uint,
-                                                Scope: DIScope,
-                                                InlinedAt: MetadataRef)
-                                                -> ValueRef;
-    pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
-    pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;
-
-    pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef);
-    pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
-
-    pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
-    pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef;
-
-    pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
-    pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
-    pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
-
-    pub fn LLVMRustHasFeature(T: TargetMachineRef, s: *const c_char) -> bool;
-
-    pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef);
-    pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef);
-
-    pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
-                                       CPU: *const c_char,
-                                       Features: *const c_char,
-                                       Model: CodeModel,
-                                       Reloc: RelocMode,
-                                       Level: CodeGenOptLevel,
-                                       UseSoftFP: bool,
-                                       PositionIndependentExecutable: bool,
-                                       FunctionSections: bool,
-                                       DataSections: bool,
-                                       TrapUnreachable: bool,
-                                       Singlethread: bool)
-                                       -> TargetMachineRef;
-    pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
-    pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef);
-    pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
-                                         M: ModuleRef,
-                                         DisableSimplifyLibCalls: bool);
-    pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
-                                               OptLevel: CodeGenOptLevel,
-                                               MergeFunctions: bool,
-                                               SLPVectorize: bool,
-                                               LoopVectorize: bool,
-                                               PrepareForThinLTO: bool,
-                                               PGOGenPath: *const c_char,
-                                               PGOUsePath: *const c_char);
-    pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef,
-                                  M: ModuleRef,
-                                  DisableSimplifyLibCalls: bool);
-    pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
-    pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
-                                   PM: PassManagerRef,
-                                   M: ModuleRef,
-                                   Output: *const c_char,
-                                   FileType: FileType)
-                                   -> LLVMRustResult;
-    pub fn LLVMRustPrintModule(PM: PassManagerRef,
-                               M: ModuleRef,
-                               Output: *const c_char,
-                               Demangle: extern fn(*const c_char,
-                                                   size_t,
-                                                   *mut c_char,
-                                                   size_t) -> size_t);
-    pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
-    pub fn LLVMRustPrintPasses();
-    pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
-    pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool);
-    pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t);
-    pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
-
-    pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
-    pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
-    pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
-    pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char;
-    pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char;
-    pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef);
-    pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
-    pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
-
-    pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, data: *mut *const c_char) -> size_t;
-
-    pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef);
-
-    pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
-                                           Handler: DiagnosticHandler,
-                                           DiagnosticContext: *mut c_void);
-
-    pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
-                                                pass_name_out: RustStringRef,
-                                                function_out: *mut ValueRef,
-                                                loc_line_out: *mut c_uint,
-                                                loc_column_out: *mut c_uint,
-                                                loc_filename_out: RustStringRef,
-                                                message_out: RustStringRef);
-    pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef,
-                                             cookie_out: *mut c_uint,
-                                             message_out: *mut TwineRef,
-                                             instruction_out: *mut ValueRef);
-
-    pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
-    pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
-
-    pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef,
-                                                 H: InlineAsmDiagHandler,
-                                                 CX: *mut c_void);
-
-    pub fn LLVMRustWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
-
-    pub fn LLVMRustWriteArchive(Dst: *const c_char,
-                                NumMembers: size_t,
-                                Members: *const RustArchiveMemberRef,
-                                WriteSymbtab: bool,
-                                Kind: ArchiveKind)
-                                -> LLVMRustResult;
-    pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
-                                    Name: *const c_char,
-                                    Child: ArchiveChildRef)
-                                    -> RustArchiveMemberRef;
-    pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef);
-
-    pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef);
-
-    pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
-                                         Inputs: *const ValueRef,
-                                         NumInputs: c_uint)
-                                         -> OperandBundleDefRef;
-    pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
-
-    pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
-
-    pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
-    pub fn LLVMRustUnsetComdat(V: ValueRef);
-    pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
-    pub fn LLVMRustModuleBufferCreate(M: ModuleRef) -> *mut ModuleBuffer;
-    pub fn LLVMRustModuleBufferPtr(p: *const ModuleBuffer) -> *const u8;
-    pub fn LLVMRustModuleBufferLen(p: *const ModuleBuffer) -> usize;
-    pub fn LLVMRustModuleBufferFree(p: *mut ModuleBuffer);
-    pub fn LLVMRustModuleCost(M: ModuleRef) -> u64;
-
-    pub fn LLVMRustThinLTOAvailable() -> bool;
-    pub fn LLVMRustPGOAvailable() -> bool;
-    pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef,
-                                          M: ModuleRef,
-                                          BC: *const c_char) -> bool;
-    pub fn LLVMRustThinLTOBufferCreate(M: ModuleRef) -> *mut ThinLTOBuffer;
-    pub fn LLVMRustThinLTOBufferFree(M: *mut ThinLTOBuffer);
-    pub fn LLVMRustThinLTOBufferPtr(M: *const ThinLTOBuffer) -> *const c_char;
-    pub fn LLVMRustThinLTOBufferLen(M: *const ThinLTOBuffer) -> size_t;
-    pub fn LLVMRustCreateThinLTOData(
-        Modules: *const ThinLTOModule,
-        NumModules: c_uint,
-        PreservedSymbols: *const *const c_char,
-        PreservedSymbolsLen: c_uint,
-    ) -> *mut ThinLTOData;
-    pub fn LLVMRustPrepareThinLTORename(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustPrepareThinLTOResolveWeak(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustPrepareThinLTOInternalize(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustPrepareThinLTOImport(
-        Data: *const ThinLTOData,
-        Module: ModuleRef,
-    ) -> bool;
-    pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData);
-    pub fn LLVMRustParseBitcodeForThinLTO(
-        Context: ContextRef,
-        Data: *const u8,
-        len: usize,
-        Identifier: *const c_char,
-    ) -> ModuleRef;
-    pub fn LLVMGetModuleIdentifier(M: ModuleRef, size: *mut usize) -> *const c_char;
-    pub fn LLVMRustThinLTOGetDICompileUnit(M: ModuleRef,
-                                           CU1: *mut *mut c_void,
-                                           CU2: *mut *mut c_void);
-    pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void);
-
-    pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef;
-    pub fn LLVMRustLinkerAdd(linker: LinkerRef,
-                             bytecode: *const c_char,
-                             bytecode_len: usize) -> bool;
-    pub fn LLVMRustLinkerFree(linker: LinkerRef);
-}
index 91f9b4ac03b86efe422e25689cb84742d8653a16..ffa97bd6fa59d3a385d5738440a54d8527134871 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_upper_case_globals)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-#![allow(dead_code)]
+#![feature(static_nobundle)]
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
-#![feature(box_syntax)]
-#![feature(concat_idents)]
-#![feature(libc)]
-#![feature(link_args)]
-#![feature(static_nobundle)]
-
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
 
-#[macro_use]
-extern crate bitflags;
-extern crate libc;
-
-pub use self::IntPredicate::*;
-pub use self::RealPredicate::*;
-pub use self::TypeKind::*;
-pub use self::AtomicRmwBinOp::*;
-pub use self::MetadataType::*;
-pub use self::CodeGenOptSize::*;
-pub use self::CallConv::*;
-pub use self::Linkage::*;
-
-use std::str::FromStr;
-use std::slice;
-use std::ffi::{CString, CStr};
-use std::cell::RefCell;
-use libc::{c_uint, c_char, size_t};
-
-pub mod archive_ro;
-pub mod diagnostic;
-mod ffi;
-
-pub use ffi::*;
-
-impl LLVMRustResult {
-    pub fn into_result(self) -> Result<(), ()> {
-        match self {
-            LLVMRustResult::Success => Ok(()),
-            LLVMRustResult::Failure => Err(()),
-        }
-    }
-}
-
-pub fn AddFunctionAttrStringValue(llfn: ValueRef,
-                                  idx: AttributePlace,
-                                  attr: &CStr,
-                                  value: &CStr) {
-    unsafe {
-        LLVMRustAddFunctionAttrStringValue(llfn,
-                                           idx.as_uint(),
-                                           attr.as_ptr(),
-                                           value.as_ptr())
-    }
-}
-
-#[derive(Copy, Clone)]
-pub enum AttributePlace {
-    ReturnValue,
-    Argument(u32),
-    Function,
-}
-
-impl AttributePlace {
-    pub fn as_uint(self) -> c_uint {
-        match self {
-            AttributePlace::ReturnValue => 0,
-            AttributePlace::Argument(i) => 1 + i,
-            AttributePlace::Function => !0,
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum CodeGenOptSize {
-    CodeGenOptSizeNone = 0,
-    CodeGenOptSizeDefault = 1,
-    CodeGenOptSizeAggressive = 2,
-}
-
-impl FromStr for ArchiveKind {
-    type Err = ();
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "gnu" => Ok(ArchiveKind::K_GNU),
-            "bsd" => Ok(ArchiveKind::K_BSD),
-            "coff" => Ok(ArchiveKind::K_COFF),
-            _ => Err(()),
-        }
-    }
-}
-
-#[allow(missing_copy_implementations)]
-pub enum RustString_opaque {}
-type RustStringRef = *mut RustString_opaque;
-type RustStringRepr = *mut RefCell<Vec<u8>>;
-
-/// Appending to a Rust string -- used by RawRustStringOstream.
-#[no_mangle]
-pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef,
-                                                 ptr: *const c_char,
-                                                 size: size_t) {
-    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
-
-    let sr = sr as RustStringRepr;
-    (*sr).borrow_mut().extend_from_slice(slice);
-}
-
-pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
-    unsafe {
-        LLVMSetInstructionCallConv(instr, cc as c_uint);
-    }
-}
-pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
-    unsafe {
-        LLVMSetFunctionCallConv(fn_, cc as c_uint);
-    }
-}
-
-// Externally visible symbols that might appear in multiple codegen units need to appear in
-// their own comdat section so that the duplicates can be discarded at link time. This can for
-// example happen for generics when using multiple codegen units. This function simply uses the
-// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
-// function.
-// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
-pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
-    unsafe {
-        LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
-    }
-}
-
-pub fn UnsetComdat(val: ValueRef) {
-    unsafe {
-        LLVMRustUnsetComdat(val);
-    }
-}
-
-pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
-    unsafe {
-        LLVMSetUnnamedAddr(global, unnamed as Bool);
-    }
-}
-
-pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
-    unsafe {
-        LLVMSetThreadLocal(global, is_thread_local as Bool);
-    }
-}
-pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) {
-    unsafe {
-        LLVMSetThreadLocalMode(global, mode);
-    }
-}
-
-impl Attribute {
-    pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
-        unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
-    }
-
-    pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
-        unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
-    }
-
-    pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
-        unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
-    }
-
-    pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) {
-        if set {
-            self.apply_llfn(idx, llfn);
-        } else {
-            self.unapply_llfn(idx, llfn);
-        }
-    }
-}
-
-// Memory-managed interface to target data.
-
-struct TargetData {
-    lltd: TargetDataRef,
-}
-
-impl Drop for TargetData {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeTargetData(self.lltd);
-        }
-    }
-}
-
-fn mk_target_data(string_rep: &str) -> TargetData {
-    let string_rep = CString::new(string_rep).unwrap();
-    TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } }
-}
-
-// Memory-managed interface to object files.
-
-pub struct ObjectFile {
-    pub llof: ObjectFileRef,
-}
-
-unsafe impl Send for ObjectFile {}
-
-impl ObjectFile {
-    // This will take ownership of llmb
-    pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
-        unsafe {
-            let llof = LLVMCreateObjectFile(llmb);
-            if llof as isize == 0 {
-                // LLVMCreateObjectFile took ownership of llmb
-                return None;
-            }
-
-            Some(ObjectFile { llof: llof })
-        }
-    }
-}
-
-impl Drop for ObjectFile {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeObjectFile(self.llof);
-        }
-    }
-}
-
-// Memory-managed interface to section iterators.
-
-pub struct SectionIter {
-    pub llsi: SectionIteratorRef,
-}
-
-impl Drop for SectionIter {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeSectionIterator(self.llsi);
-        }
-    }
-}
-
-pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
-    unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
-}
-
-/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
-pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
-    unsafe {
-        assert!(index < LLVMCountParams(llfn),
-            "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
-        LLVMGetParam(llfn, index)
-    }
-}
-
-fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
-    unsafe {
-        let num_params = LLVMCountParams(llfn);
-
-        (0..num_params).map(|idx| LLVMGetParam(llfn, idx)).collect()
-    }
-}
-
-pub fn build_string<F>(f: F) -> Option<String>
-    where F: FnOnce(RustStringRef)
-{
-    let mut buf = RefCell::new(Vec::new());
-    f(&mut buf as RustStringRepr as RustStringRef);
-    String::from_utf8(buf.into_inner()).ok()
-}
-
-pub unsafe fn twine_to_string(tr: TwineRef) -> String {
-    build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
-}
+// NOTE: This crate only exists to allow linking on mingw targets.
 
+/// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`.
+/// NB: this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s.
 pub fn initialize_available_targets() {
     macro_rules! init_target(
         ($cfg:meta, $($method:ident),*) => { {
@@ -360,6 +90,12 @@ fn init() { }
                  LLVMInitializeMSP430Target,
                  LLVMInitializeMSP430TargetMC,
                  LLVMInitializeMSP430AsmPrinter);
+    init_target!(llvm_component = "riscv",
+                 LLVMInitializeRISCVTargetInfo,
+                 LLVMInitializeRISCVTarget,
+                 LLVMInitializeRISCVTargetMC,
+                 LLVMInitializeRISCVAsmPrinter,
+                 LLVMInitializeRISCVAsmParser);
     init_target!(llvm_component = "sparc",
                  LLVMInitializeSparcTargetInfo,
                  LLVMInitializeSparcTarget,
@@ -383,43 +119,3 @@ fn init() { }
                  LLVMInitializeWebAssemblyTargetMC,
                  LLVMInitializeWebAssemblyAsmPrinter);
 }
-
-pub fn last_error() -> Option<String> {
-    unsafe {
-        let cstr = LLVMRustGetLastError();
-        if cstr.is_null() {
-            None
-        } else {
-            let err = CStr::from_ptr(cstr).to_bytes();
-            let err = String::from_utf8_lossy(err).to_string();
-            libc::free(cstr as *mut _);
-            Some(err)
-        }
-    }
-}
-
-pub struct OperandBundleDef {
-    inner: OperandBundleDefRef,
-}
-
-impl OperandBundleDef {
-    pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
-        let name = CString::new(name).unwrap();
-        let def = unsafe {
-            LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
-        };
-        OperandBundleDef { inner: def }
-    }
-
-    pub fn raw(&self) -> OperandBundleDefRef {
-        self.inner
-    }
-}
-
-impl Drop for OperandBundleDef {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMRustFreeOperandBundleDef(self.inner);
-        }
-    }
-}
index 338824d5efe4caa862256121941b11a7e38bdbce..6142fe78149ce219c5715d8c43f629d0c07d71a9 100644 (file)
@@ -20,3 +20,4 @@ serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc_metadata_utils = { path = "../librustc_metadata_utils" }
index 4f808dee61f2173f5554a4efb135cde271188fe1..62c06aac1df0ecb5bb3006fdcc97a5ed4b8c9ecd 100644 (file)
 use rustc::session::config::{Sanitizer, self};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 use rustc::session::search_paths::PathKind;
-use rustc::middle;
-use rustc::middle::cstore::{validate_crate_name, ExternCrate, ExternCrateSource};
+use rustc::middle::cstore::{ExternCrate, ExternCrateSource};
 use rustc::util::common::record_time;
 use rustc::util::nodemap::FxHashSet;
 use rustc::hir::map::Definitions;
 
+use rustc_metadata_utils::validate_crate_name;
+
 use std::ops::Deref;
 use std::path::PathBuf;
 use std::{cmp, fs};
@@ -626,7 +627,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // If we're only compiling an rlib, then there's no need to select a
         // panic runtime, so we just skip this section entirely.
         let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| {
-            *ct != config::CrateTypeRlib
+            *ct != config::CrateType::Rlib
         });
         if !any_non_rlib {
             info!("panic runtime injection skipped, only generating rlib");
@@ -737,13 +738,13 @@ fn inject_sanitizer_runtime(&mut self) {
                 if !self.sess.crate_types.borrow().iter().all(|ct| {
                     match *ct {
                         // Link the runtime
-                        config::CrateTypeStaticlib |
-                        config::CrateTypeExecutable => true,
+                        config::CrateType::Staticlib |
+                        config::CrateType::Executable => true,
                         // This crate will be compiled with the required
                         // instrumentation pass
-                        config::CrateTypeRlib |
-                        config::CrateTypeDylib |
-                        config::CrateTypeCdylib =>
+                        config::CrateType::Rlib |
+                        config::CrateType::Dylib |
+                        config::CrateType::Cdylib =>
                             false,
                         _ => {
                             self.sess.err(&format!("Only executables, staticlibs, \
@@ -759,10 +760,10 @@ fn inject_sanitizer_runtime(&mut self) {
                 if !self.sess.crate_types.borrow().iter().all(|ct| {
                     match *ct {
                         // Link the runtime
-                        config::CrateTypeExecutable => true,
+                        config::CrateType::Executable => true,
                         // This crate will be compiled with the required
                         // instrumentation pass
-                        config::CrateTypeRlib => false,
+                        config::CrateType::Rlib => false,
                         _ => {
                             self.sess.err(&format!("Only executables and rlibs can be \
                                                     compiled with `-Z sanitizer`"));
@@ -852,12 +853,12 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         let mut need_exe_alloc = false;
         for ct in self.sess.crate_types.borrow().iter() {
             match *ct {
-                config::CrateTypeExecutable => need_exe_alloc = true,
-                config::CrateTypeDylib |
-                config::CrateTypeProcMacro |
-                config::CrateTypeCdylib |
-                config::CrateTypeStaticlib => need_lib_alloc = true,
-                config::CrateTypeRlib => {}
+                config::CrateType::Executable => need_exe_alloc = true,
+                config::CrateType::Dylib |
+                config::CrateType::ProcMacro |
+                config::CrateType::Cdylib |
+                config::CrateType::Staticlib => need_lib_alloc = true,
+                config::CrateType::Rlib => {}
             }
         }
         if !need_lib_alloc && !need_exe_alloc {
@@ -1056,8 +1057,8 @@ fn inject_dependency_if(&self,
     }
 }
 
-impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
-    fn postprocess(&mut self, krate: &ast::Crate) {
+impl<'a> CrateLoader<'a> {
+    pub fn postprocess(&mut self, krate: &ast::Crate) {
         // inject the sanitizer runtime before the allocator runtime because all
         // sanitizers force the use of the `alloc_system` allocator
         self.inject_sanitizer_runtime();
@@ -1070,7 +1071,9 @@ fn postprocess(&mut self, krate: &ast::Crate) {
         }
     }
 
-    fn process_extern_crate(&mut self, item: &ast::Item, definitions: &Definitions) -> CrateNum {
+    pub fn process_extern_crate(
+        &mut self, item: &ast::Item, definitions: &Definitions,
+    ) -> CrateNum {
         match item.node {
             ast::ItemKind::ExternCrate(orig_name) => {
                 debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
@@ -1113,7 +1116,7 @@ fn process_extern_crate(&mut self, item: &ast::Item, definitions: &Definitions)
         }
     }
 
-    fn process_path_extern(
+    pub fn process_path_extern(
         &mut self,
         name: Symbol,
         span: Span,
@@ -1137,7 +1140,7 @@ fn process_path_extern(
         cnum
     }
 
-    fn process_use_extern(
+    pub fn process_use_extern(
         &mut self,
         name: Symbol,
         span: Span,
index d93a7f9526e1aed9377d69d89acba136b4d24de8..2d3e3080c89e390df630b41bab99c7c81d8b2624 100644 (file)
@@ -93,6 +93,11 @@ pub struct CStore {
     pub metadata_loader: Box<dyn MetadataLoader + Sync>,
 }
 
+pub enum LoadedMacro {
+    MacroDef(ast::Item),
+    ProcMacro(Lrc<SyntaxExtension>),
+}
+
 impl CStore {
     pub fn new(metadata_loader: Box<dyn MetadataLoader + Sync>) -> CStore {
         CStore {
index e3a7918f8c5897df13ba8790fca77ce962daa3a9..916c0920e0b4b2dfa7c20376d9f668ed9122d61c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use cstore;
+use cstore::{self, LoadedMacro};
 use encoder;
 use link_args;
 use native_libs;
@@ -17,8 +17,8 @@
 
 use rustc::ty::query::QueryConfig;
 use rustc::middle::cstore::{CrateStore, DepKind,
-                            MetadataLoader, LinkMeta,
-                            LoadedMacro, EncodedMetadata, NativeLibraryKind};
+                            LinkMeta,
+                            EncodedMetadata, NativeLibraryKind};
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
 use rustc::hir::def;
@@ -411,36 +411,8 @@ fn is_const_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
     };
 }
 
-impl CrateStore for cstore::CStore {
-    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any> {
-        self.get_crate_data(krate)
-    }
-
-    fn metadata_loader(&self) -> &dyn MetadataLoader {
-        &*self.metadata_loader
-    }
-
-    fn visibility_untracked(&self, def: DefId) -> ty::Visibility {
-        self.get_crate_data(def.krate).get_visibility(def.index)
-    }
-
-    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
-        self.get_crate_data(def.krate).get_generics(def.index, sess)
-    }
-
-    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
-    {
-        self.get_crate_data(def.krate).get_associated_item(def.index)
-    }
-
-    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
-    {
-        let data = self.get_crate_data(cnum);
-        let r = *data.dep_kind.lock();
-        r
-    }
-
-    fn export_macros_untracked(&self, cnum: CrateNum) {
+impl cstore::CStore {
+    pub fn export_macros_untracked(&self, cnum: CrateNum) {
         let data = self.get_crate_data(cnum);
         let mut dep_kind = data.dep_kind.lock();
         if *dep_kind == DepKind::UnexportedMacrosOnly {
@@ -448,69 +420,28 @@ fn export_macros_untracked(&self, cnum: CrateNum) {
         }
     }
 
-    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol
-    {
-        self.get_crate_data(cnum).name
-    }
-
-    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator
-    {
-        self.get_crate_data(cnum).root.disambiguator
-    }
-
-    fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh
-    {
-        self.get_crate_data(cnum).root.hash
+    pub fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind {
+        let data = self.get_crate_data(cnum);
+        let r = *data.dep_kind.lock();
+        r
     }
 
-    fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition
-    {
+    pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition {
         self.get_crate_data(cnum).root.edition
     }
 
-    /// Returns the `DefKey` for a given `DefId`. This indicates the
-    /// parent `DefId` as well as some idea of what kind of data the
-    /// `DefId` refers to.
-    fn def_key(&self, def: DefId) -> DefKey {
-        // Note: loading the def-key (or def-path) for a def-id is not
-        // a *read* of its metadata. This is because the def-id is
-        // really just an interned shorthand for a def-path, which is the
-        // canonical name for an item.
-        //
-        // self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).def_key(def.index)
-    }
-
-    fn def_path(&self, def: DefId) -> DefPath {
-        // See `Note` above in `def_key()` for why this read is
-        // commented out:
-        //
-        // self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).def_path(def.index)
-    }
-
-    fn def_path_hash(&self, def: DefId) -> DefPathHash {
-        self.get_crate_data(def.krate).def_path_hash(def.index)
-    }
-
-    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable> {
-        self.get_crate_data(cnum).def_path_table.clone()
-    }
-
-    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>
-    {
+    pub fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
         self.get_crate_data(def.krate).get_struct_field_names(def.index)
     }
 
-    fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export>
-    {
+    pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export> {
         let mut result = vec![];
         self.get_crate_data(def_id.krate)
             .each_child_of_item(def_id.index, |child| result.push(child), sess);
         result
     }
 
-    fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
+    pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
         let data = self.get_crate_data(id.krate);
         if let Some(ref proc_macros) = data.proc_macros {
             return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
@@ -559,6 +490,64 @@ fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
         })
     }
 
+    pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem {
+        self.get_crate_data(def.krate).get_associated_item(def.index)
+    }
+}
+
+impl CrateStore for cstore::CStore {
+    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any> {
+        self.get_crate_data(krate)
+    }
+
+    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
+        self.get_crate_data(def.krate).get_generics(def.index, sess)
+    }
+
+    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol
+    {
+        self.get_crate_data(cnum).name
+    }
+
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator
+    {
+        self.get_crate_data(cnum).root.disambiguator
+    }
+
+    fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh
+    {
+        self.get_crate_data(cnum).root.hash
+    }
+
+    /// Returns the `DefKey` for a given `DefId`. This indicates the
+    /// parent `DefId` as well as some idea of what kind of data the
+    /// `DefId` refers to.
+    fn def_key(&self, def: DefId) -> DefKey {
+        // Note: loading the def-key (or def-path) for a def-id is not
+        // a *read* of its metadata. This is because the def-id is
+        // really just an interned shorthand for a def-path, which is the
+        // canonical name for an item.
+        //
+        // self.dep_graph.read(DepNode::MetaData(def));
+        self.get_crate_data(def.krate).def_key(def.index)
+    }
+
+    fn def_path(&self, def: DefId) -> DefPath {
+        // See `Note` above in `def_key()` for why this read is
+        // commented out:
+        //
+        // self.dep_graph.read(DepNode::MetaData(def));
+        self.get_crate_data(def.krate).def_path(def.index)
+    }
+
+    fn def_path_hash(&self, def: DefId) -> DefPathHash {
+        self.get_crate_data(def.krate).def_path_hash(def.index)
+    }
+
+    fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable> {
+        self.get_crate_data(cnum).def_path_table.clone()
+    }
+
     fn crates_untracked(&self) -> Vec<CrateNum>
     {
         let mut result = vec![];
index 7ed991e0de3a1d010474cd55462dfb6ba5fea203..4a02a278bc14ebb5bbe38370124840a98c739f90 100644 (file)
@@ -28,7 +28,7 @@
 use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
 use rustc::ty::codec::{self as ty_codec, TyEncoder};
 
-use rustc::session::config::{self, CrateTypeProcMacro};
+use rustc::session::config::{self, CrateType};
 use rustc::util::nodemap::FxHashMap;
 
 use rustc_data_structures::stable_hasher::StableHasher;
@@ -478,7 +478,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
 
         let attrs = tcx.hir.krate_attrs();
         let link_meta = self.link_meta;
-        let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
+        let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
         let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator");
         let has_global_allocator = *tcx.sess.has_global_allocator.get();
 
@@ -1542,7 +1542,7 @@ fn encode_exported_symbols(&mut self,
     }
 
     fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
-        match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
+        match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) {
             Some(arr) => {
                 self.lazy_seq(arr.iter().map(|slot| {
                     match *slot {
index 5cba0387d17bb6ba4ff46ae92076c47a6954051e..798b631989bd57ad642ed9cc4ae30e91f4c74306 100644 (file)
@@ -37,6 +37,7 @@
 extern crate rustc_errors as errors;
 extern crate syntax_ext;
 extern crate proc_macro;
+extern crate rustc_metadata_utils;
 
 #[macro_use]
 extern crate rustc;
diff --git a/src/librustc_metadata_utils/Cargo.toml b/src/librustc_metadata_utils/Cargo.toml
new file mode 100644 (file)
index 0000000..4a5e203
--- /dev/null
@@ -0,0 +1,14 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_metadata_utils"
+version = "0.0.0"
+
+[lib]
+name = "rustc_metadata_utils"
+path = "lib.rs"
+crate-type = ["dylib"]
+
+[dependencies]
+rustc = { path = "../librustc" }
+syntax = { path = "../libsyntax" }
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_metadata_utils/lib.rs b/src/librustc_metadata_utils/lib.rs
new file mode 100644 (file)
index 0000000..a1e5150
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use]
+extern crate rustc;
+extern crate syntax_pos;
+
+use rustc::session::Session;
+use syntax_pos::Span;
+
+pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
+    let mut err_count = 0;
+    {
+        let mut say = |s: &str| {
+            match (sp, sess) {
+                (_, None) => bug!("{}", s),
+                (Some(sp), Some(sess)) => sess.span_err(sp, s),
+                (None, Some(sess)) => sess.err(s),
+            }
+            err_count += 1;
+        };
+        if s.is_empty() {
+            say("crate name must not be empty");
+        }
+        for c in s.chars() {
+            if c.is_alphanumeric() { continue }
+            if c == '_'  { continue }
+            say(&format!("invalid character `{}` in crate name: `{}`", c, s));
+        }
+    }
+
+    if err_count > 0 {
+        sess.unwrap().abort_if_errors();
+    }
+}
index e2ac7dde558547bae248f6310efc9b456a1e9503..aabed6686858fddf6fe579d235b019a4130454f0 100644 (file)
 
 use borrow_check::WriteKind;
 use rustc::middle::region::ScopeTree;
+use rustc::mir::VarBindingForm;
 use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local};
 use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place};
 use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind};
-use rustc::mir::VarBindingForm;
 use rustc::ty;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
 use super::borrow_set::BorrowData;
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     pub(super) fn report_use_of_moved_or_uninitialized(
         &mut self,
-        _context: Context,
+        context: Context,
         desired_action: InitializationRequiringAction,
         (place, span): (&Place<'tcx>, Span),
         mpi: MovePathIndex,
         curr_move_out: &FlowAtLocation<MovingOutStatements<'_, 'gcx, 'tcx>>,
     ) {
+        let use_spans = self
+            .move_spans(place, context.loc)
+            .or_else(|| self.borrow_spans(span, context.loc));
+        let span = use_spans.args_or_use();
+
         let mois = self.move_data.path_map[mpi]
             .iter()
             .filter(|moi| curr_move_out.contains(moi))
@@ -58,16 +64,21 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                 Some(name) => format!("`{}`", name),
                 None => "value".to_owned(),
             };
-            let mut err = self.tcx
-                .cannot_act_on_uninitialized_variable(
-                    span,
-                    desired_action.as_noun(),
-                    &self
-                        .describe_place_with_options(place, IncludingDowncast(true))
-                        .unwrap_or("_".to_owned()),
-                    Origin::Mir,
-                );
+            let mut err = self.tcx.cannot_act_on_uninitialized_variable(
+                span,
+                desired_action.as_noun(),
+                &self
+                    .describe_place_with_options(place, IncludingDowncast(true))
+                    .unwrap_or("_".to_owned()),
+                Origin::Mir,
+            );
             err.span_label(span, format!("use of possibly uninitialized {}", item_msg));
+
+            use_spans.var_span_label(
+                &mut err,
+                format!("{} occurs due to use in closure", desired_action.as_noun()),
+            );
+
             err.buffer(&mut self.errors_buffer);
         } else {
             let msg = ""; //FIXME: add "partially " or "collaterally "
@@ -82,11 +93,18 @@ pub(super) fn report_use_of_moved_or_uninitialized(
 
             let mut is_loop_move = false;
             for moi in &mois {
-                let move_msg = ""; //FIXME: add " (into closure)"
-                let move_span = self
-                    .mir
-                    .source_info(self.move_data.moves[**moi].source)
-                    .span;
+                let move_out = self.move_data.moves[**moi];
+                let moved_place = &self.move_data.move_paths[move_out.path].place;
+
+                let move_spans = self.move_spans(moved_place, move_out.source);
+                let move_span = move_spans.args_or_use();
+
+                let move_msg = if move_spans.for_closure() {
+                    " into closure"
+                } else {
+                    ""
+                };
+
                 if span == move_span {
                     err.span_label(
                         span,
@@ -95,8 +113,15 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                     is_loop_move = true;
                 } else {
                     err.span_label(move_span, format!("value moved{} here", move_msg));
+                    move_spans.var_span_label(&mut err, "variable moved due to use in closure");
                 };
             }
+
+            use_spans.var_span_label(
+                &mut err,
+                format!("{} occurs due to use in closure", desired_action.as_noun()),
+            );
+
             if !is_loop_move {
                 err.span_label(
                     span,
@@ -150,7 +175,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
     pub(super) fn report_move_out_while_borrowed(
         &mut self,
         context: Context,
-        (place, span): (&Place<'tcx>, Span),
+        (place, _span): (&Place<'tcx>, Span),
         borrow: &BorrowData<'tcx>,
     ) {
         let tcx = self.tcx;
@@ -162,16 +187,25 @@ pub(super) fn report_move_out_while_borrowed(
             Some(name) => format!("`{}`", name),
             None => "value".to_owned(),
         };
+
+        let borrow_spans = self.retrieve_borrow_spans(borrow);
+        let borrow_span = borrow_spans.args_or_use();
+
+        let move_spans = self.move_spans(place, context.loc);
+        let span = move_spans.args_or_use();
+
         let mut err = tcx.cannot_move_when_borrowed(
             span,
             &self.describe_place(place).unwrap_or("_".to_owned()),
             Origin::Mir,
         );
-        err.span_label(
-            self.retrieve_borrow_span(borrow),
-            format!("borrow of {} occurs here", borrow_msg),
-        );
+        err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg));
         err.span_label(span, format!("move out of {} occurs here", value_msg));
+
+        borrow_spans.var_span_label(&mut err, "borrow occurs due to use in closure");
+
+        move_spans.var_span_label(&mut err, "move occurs due to use in closure");
+
         self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
         err.buffer(&mut self.errors_buffer);
     }
@@ -179,92 +213,38 @@ pub(super) fn report_move_out_while_borrowed(
     pub(super) fn report_use_while_mutably_borrowed(
         &mut self,
         context: Context,
-        (place, span): (&Place<'tcx>, Span),
+        (place, _span): (&Place<'tcx>, Span),
         borrow: &BorrowData<'tcx>,
     ) {
         let tcx = self.tcx;
+
+        let borrow_spans = self.retrieve_borrow_spans(borrow);
+        let borrow_span = borrow_spans.args_or_use();
+
+        // Conflicting borrows are reported separately, so only check for move
+        // captures.
+        let use_spans = self.move_spans(place, context.loc);
+        let span = use_spans.var_or_use();
+
         let mut err = tcx.cannot_use_when_mutably_borrowed(
             span,
             &self.describe_place(place).unwrap_or("_".to_owned()),
-            self.retrieve_borrow_span(borrow),
+            borrow_span,
             &self
                 .describe_place(&borrow.borrowed_place)
                 .unwrap_or("_".to_owned()),
             Origin::Mir,
         );
 
-        self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
-        err.buffer(&mut self.errors_buffer);
-    }
-
-    /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of
-    /// the local assigned at `location`.
-    /// This is done by searching in statements succeeding `location`
-    /// and originating from `maybe_closure_span`.
-    pub(super) fn find_closure_span(
-        &self,
-        maybe_closure_span: Span,
-        location: Location,
-    ) -> Option<(Span, Span)> {
-        use rustc::hir::ExprKind::Closure;
-        use rustc::mir::AggregateKind;
-
-        let local = match self.mir[location.block]
-            .statements
-            .get(location.statement_index)
-        {
-            Some(&Statement {
-                kind: StatementKind::Assign(Place::Local(local), _),
-                ..
-            }) => local,
-            _ => return None,
-        };
-
-        for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
-            if maybe_closure_span != stmt.source_info.span {
-                break;
-            }
+        borrow_spans.var_span_label(&mut err, {
+            let place = &borrow.borrowed_place;
+            let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
 
-            if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind {
-                if let AggregateKind::Closure(def_id, _) = **kind {
-                    debug!("find_closure_span: found closure {:?}", places);
+            format!("borrow occurs due to use of `{}` in closure", desc_place)
+        });
 
-                    return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
-                        let args_span = if let Closure(_, _, _, span, _) =
-                            self.tcx.hir.expect_expr(node_id).node
-                        {
-                            span
-                        } else {
-                            return None;
-                        };
-
-                        self.tcx
-                            .with_freevars(node_id, |freevars| {
-                                for (v, place) in freevars.iter().zip(places) {
-                                    match *place {
-                                        Operand::Copy(Place::Local(l))
-                                        | Operand::Move(Place::Local(l)) if local == l =>
-                                        {
-                                            debug!(
-                                                "find_closure_span: found captured local {:?}",
-                                                l
-                                            );
-                                            return Some(v.span);
-                                        }
-                                        _ => {}
-                                    }
-                                }
-                                None
-                            })
-                            .map(|var_span| (args_span, var_span))
-                    } else {
-                        None
-                    };
-                }
-            }
-        }
-
-        None
+        self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
+        err.buffer(&mut self.errors_buffer);
     }
 
     pub(super) fn report_conflicting_borrow(
@@ -274,14 +254,11 @@ pub(super) fn report_conflicting_borrow(
         gen_borrow_kind: BorrowKind,
         issued_borrow: &BorrowData<'tcx>,
     ) {
-        let issued_span = self.retrieve_borrow_span(issued_borrow);
+        let issued_spans = self.retrieve_borrow_spans(issued_borrow);
+        let issued_span = issued_spans.args_or_use();
 
-        let new_closure_span = self.find_closure_span(span, context.loc);
-        let span = new_closure_span.map(|(args, _)| args).unwrap_or(span);
-        let old_closure_span = self.find_closure_span(issued_span, issued_borrow.reserve_location);
-        let issued_span = old_closure_span
-            .map(|(args, _)| args)
-            .unwrap_or(issued_span);
+        let borrow_spans = self.borrow_spans(span, context.loc);
+        let span = borrow_spans.args_or_use();
 
         let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
         let tcx = self.tcx;
@@ -368,23 +345,28 @@ pub(super) fn report_conflicting_borrow(
             (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(),
         };
 
-        if let Some((_, var_span)) = old_closure_span {
-            let place = &issued_borrow.borrowed_place;
-            let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
-
-            err.span_label(
-                var_span,
+        if issued_spans == borrow_spans {
+            borrow_spans.var_span_label(
+                &mut err,
                 format!(
-                    "previous borrow occurs due to use of `{}` in closure",
+                    "borrows occur due to use of `{}` in closure",
                     desc_place
                 ),
             );
-        }
+        } else {
+            let borrow_place = &issued_borrow.borrowed_place;
+            let borrow_place_desc = self.describe_place(borrow_place).unwrap_or("_".to_owned());
+            issued_spans.var_span_label(
+                &mut err,
+                format!(
+                    "first borrow occurs due to use of `{}` in closure",
+                    borrow_place_desc
+                ),
+            );
 
-        if let Some((_, var_span)) = new_closure_span {
-            err.span_label(
-                var_span,
-                format!("borrow occurs due to use of `{}` in closure", desc_place),
+            borrow_spans.var_span_label(
+                &mut err,
+                format!("second borrow occurs due to use of `{}` in closure", desc_place),
             );
         }
 
@@ -407,7 +389,9 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
             .last()
             .unwrap();
 
-        let borrow_span = self.mir.source_info(borrow.reserve_location).span;
+        let borrow_spans = self.retrieve_borrow_spans(borrow);
+        let borrow_span = borrow_spans.var_or_use();
+
         let proper_span = match *root_place {
             Place::Local(local) => self.mir.local_decls[local].source_info.span,
             _ => drop_span,
@@ -427,30 +411,30 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
         self.access_place_error_reported
             .insert((root_place.clone(), borrow_span));
 
-        match &self.describe_place(&borrow.borrowed_place) {
-            Some(name) => {
-                self.report_local_value_does_not_live_long_enough(
-                    context,
-                    name,
-                    &scope_tree,
-                    &borrow,
-                    drop_span,
-                    borrow_span,
-                    proper_span,
-                    kind.map(|k| (k, place_span.0)),
-                );
-            }
-            None => {
-                self.report_temporary_value_does_not_live_long_enough(
-                    context,
-                    &scope_tree,
-                    &borrow,
-                    drop_span,
-                    borrow_span,
-                    proper_span,
-                );
-            }
-        }
+        let mut err = match &self.describe_place(&borrow.borrowed_place) {
+            Some(name) => self.report_local_value_does_not_live_long_enough(
+                context,
+                name,
+                &scope_tree,
+                &borrow,
+                drop_span,
+                borrow_span,
+                proper_span,
+                kind.map(|k| (k, place_span.0)),
+            ),
+            None => self.report_temporary_value_does_not_live_long_enough(
+                context,
+                &scope_tree,
+                &borrow,
+                drop_span,
+                borrow_span,
+                proper_span,
+            ),
+        };
+
+        borrow_spans.args_span_label(&mut err, "value captured here");
+
+        err.buffer(&mut self.errors_buffer);
     }
 
     fn report_local_value_does_not_live_long_enough(
@@ -463,7 +447,7 @@ fn report_local_value_does_not_live_long_enough(
         borrow_span: Span,
         _proper_span: Span,
         kind_place: Option<(WriteKind, &Place<'tcx>)>,
-    ) {
+    ) -> DiagnosticBuilder<'cx> {
         debug!(
             "report_local_value_does_not_live_long_enough(\
              {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
@@ -481,7 +465,7 @@ fn report_local_value_does_not_live_long_enough(
         );
 
         self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err);
-        err.buffer(&mut self.errors_buffer);
+        err
     }
 
     fn report_temporary_value_does_not_live_long_enough(
@@ -492,7 +476,7 @@ fn report_temporary_value_does_not_live_long_enough(
         drop_span: Span,
         _borrow_span: Span,
         proper_span: Span,
-    ) {
+    ) -> DiagnosticBuilder<'cx> {
         debug!(
             "report_temporary_value_does_not_live_long_enough(\
              {:?}, {:?}, {:?}, {:?}, {:?}\
@@ -507,7 +491,7 @@ fn report_temporary_value_does_not_live_long_enough(
         err.span_label(drop_span, "temporary value only lives until here");
 
         self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
-        err.buffer(&mut self.errors_buffer);
+        err
     }
 
     pub(super) fn report_illegal_mutation_of_borrowed(
@@ -516,14 +500,19 @@ pub(super) fn report_illegal_mutation_of_borrowed(
         (place, span): (&Place<'tcx>, Span),
         loan: &BorrowData<'tcx>,
     ) {
+        let loan_spans = self.retrieve_borrow_spans(loan);
+        let loan_span = loan_spans.args_or_use();
+
         let tcx = self.tcx;
         let mut err = tcx.cannot_assign_to_borrowed(
             span,
-            self.retrieve_borrow_span(loan),
+            loan_span,
             &self.describe_place(place).unwrap_or("_".to_owned()),
             Origin::Mir,
         );
 
+        loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure");
+
         self.explain_why_borrow_contains_point(context, loan, None, &mut err);
 
         err.buffer(&mut self.errors_buffer);
@@ -556,12 +545,22 @@ pub(super) fn report_illegal_reassignment(
         // PATTERN;) then make the error refer to that local, rather than the
         // place being assigned later.
         let (place_description, assigned_span) = match local_decl {
-            Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Clear), .. })
-            | Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Set(
-                BindingForm::Var(VarBindingForm {
-                    opt_match_place: None, ..
-            }))), ..})
-            | Some(LocalDecl { is_user_variable: None, .. })
+            Some(LocalDecl {
+                is_user_variable: Some(ClearCrossCrate::Clear),
+                ..
+            })
+            | Some(LocalDecl {
+                is_user_variable:
+                    Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                        opt_match_place: None,
+                        ..
+                    }))),
+                ..
+            })
+            | Some(LocalDecl {
+                is_user_variable: None,
+                ..
+            })
             | None => (self.describe_place(place), assigned_span),
             Some(decl) => (self.describe_place(err_place), decl.source_info.span),
         };
@@ -647,8 +646,8 @@ fn append_place_to_string(
             Place::Projection(ref proj) => {
                 match proj.elem {
                     ProjectionElem::Deref => {
-                        let upvar_field_projection = place.is_upvar_field_projection(
-                            self.mir, &self.tcx);
+                        let upvar_field_projection =
+                            place.is_upvar_field_projection(self.mir, &self.tcx);
                         if let Some(field) = upvar_field_projection {
                             let var_index = field.index();
                             let name = self.mir.upvar_decls[var_index].debug_name.to_string();
@@ -666,8 +665,9 @@ fn append_place_to_string(
                                     &including_downcast,
                                 )?;
                             } else if let Place::Local(local) = proj.base {
-                                if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
-                                    = self.mir.local_decls[local].is_user_variable {
+                                if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
+                                    self.mir.local_decls[local].is_user_variable
+                                {
                                     self.append_place_to_string(
                                         &proj.base,
                                         buf,
@@ -708,8 +708,8 @@ fn append_place_to_string(
                     ProjectionElem::Field(field, _ty) => {
                         autoderef = true;
 
-                        let upvar_field_projection = place.is_upvar_field_projection(
-                            self.mir, &self.tcx);
+                        let upvar_field_projection =
+                            place.is_upvar_field_projection(self.mir, &self.tcx);
                         if let Some(field) = upvar_field_projection {
                             let var_index = field.index();
                             let name = self.mir.upvar_decls[var_index].debug_name.to_string();
@@ -810,7 +810,9 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
                 ty::TyAdt(def, _) => if def.is_enum() {
                     field.index().to_string()
                 } else {
-                    def.non_enum_variant().fields[field.index()].ident.to_string()
+                    def.non_enum_variant().fields[field.index()]
+                        .ident
+                        .to_string()
                 },
                 ty::TyTuple(_) => field.index().to_string(),
                 ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
@@ -839,11 +841,6 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
         }
     }
 
-    // Retrieve span of given borrow from the current MIR representation
-    crate fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
-        self.mir.source_info(borrow.reserve_location).span
-    }
-
     // Retrieve type of a place for the current MIR representation
     fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option<ty::Ty> {
         match place {
@@ -860,3 +857,205 @@ fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option<ty::Ty> {
         }
     }
 }
+
+// The span(s) associated to a use of a place.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub(super) enum UseSpans {
+    // The access is caused by capturing a variable for a closure.
+    ClosureUse {
+        // The span of the args of the closure, including the `move` keyword if
+        // it's present.
+        args_span: Span,
+        // The span of the first use of the captured variable inside the closure.
+        var_span: Span
+    },
+    // This access has a single span associated to it: common case.
+    OtherUse(Span),
+}
+
+impl UseSpans {
+    pub(super) fn args_or_use(self) -> Span {
+        match self {
+            UseSpans::ClosureUse {
+                args_span: span, ..
+            }
+            | UseSpans::OtherUse(span) => span,
+        }
+    }
+
+    pub(super) fn var_or_use(self) -> Span {
+        match self {
+            UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span,
+        }
+    }
+
+    // Add a span label to the arguments of the closure, if it exists.
+    pub(super) fn args_span_label(self, err: &mut DiagnosticBuilder, message: impl Into<String>) {
+        if let UseSpans::ClosureUse { args_span, .. } = self {
+            err.span_label(args_span, message);
+        }
+    }
+
+    // Add a span label to the use of the captured variable, if it exists.
+    pub(super) fn var_span_label(self, err: &mut DiagnosticBuilder, message: impl Into<String>) {
+        if let UseSpans::ClosureUse { var_span, .. } = self {
+            err.span_label(var_span, message);
+        }
+    }
+
+    pub(super) fn for_closure(self) -> bool {
+        match self {
+            UseSpans::ClosureUse { .. } => true,
+            UseSpans::OtherUse(_) => false,
+        }
+    }
+
+    pub(super) fn or_else<F>(self, if_other: F) -> Self
+    where
+        F: FnOnce() -> Self,
+    {
+        match self {
+            closure @ UseSpans::ClosureUse { .. } => closure,
+            UseSpans::OtherUse(_) => if_other(),
+        }
+    }
+}
+
+impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
+    /// Finds the spans associated to a move or copy of move_place at location.
+    pub(super) fn move_spans(
+        &self,
+        moved_place: &Place<'tcx>, // Could also be an upvar.
+        location: Location,
+    ) -> UseSpans {
+        use self::UseSpans::*;
+        use rustc::hir::ExprKind::Closure;
+        use rustc::mir::AggregateKind;
+
+        let stmt = match self.mir[location.block]
+            .statements
+            .get(location.statement_index)
+        {
+            Some(stmt) => stmt,
+            None => return OtherUse(self.mir.source_info(location).span),
+        };
+
+        if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind {
+            if let AggregateKind::Closure(def_id, _) = **kind {
+                debug!("find_closure_move_span: found closure {:?}", places);
+
+                if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                    if let Closure(_, _, _, args_span, _) = self.tcx.hir.expect_expr(node_id).node {
+                        if let Some(var_span) = self.tcx.with_freevars(node_id, |freevars| {
+                            for (v, place) in freevars.iter().zip(places) {
+                                match place {
+                                    Operand::Copy(place) | Operand::Move(place)
+                                        if moved_place == place =>
+                                    {
+                                        debug!(
+                                            "find_closure_move_span: found captured local {:?}",
+                                            place
+                                        );
+                                        return Some(v.span);
+                                    }
+                                    _ => {}
+                                }
+                            }
+                            None
+                        }) {
+                            return ClosureUse {
+                                args_span,
+                                var_span,
+                            };
+                        }
+                    }
+                }
+            }
+        }
+
+        return OtherUse(stmt.source_info.span);
+    }
+
+    /// Finds the span of arguments of a closure (within `maybe_closure_span`)
+    /// and its usage of the local assigned at `location`.
+    /// This is done by searching in statements succeeding `location`
+    /// and originating from `maybe_closure_span`.
+    pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans {
+        use self::UseSpans::*;
+        use rustc::hir::ExprKind::Closure;
+        use rustc::mir::AggregateKind;
+
+        let local = match self.mir[location.block]
+            .statements
+            .get(location.statement_index)
+        {
+            Some(&Statement {
+                kind: StatementKind::Assign(Place::Local(local), _),
+                ..
+            }) => local,
+            _ => return OtherUse(use_span),
+        };
+
+        if self.mir.local_kind(local) != LocalKind::Temp {
+            // operands are always temporaries.
+            return OtherUse(use_span);
+        }
+
+        for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
+            if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind {
+                if let AggregateKind::Closure(def_id, _) = **kind {
+                    debug!("find_closure_borrow_span: found closure {:?}", places);
+
+                    return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                        let args_span = if let Closure(_, _, _, span, _) =
+                            self.tcx.hir.expect_expr(node_id).node
+                        {
+                            span
+                        } else {
+                            return OtherUse(use_span);
+                        };
+
+                        self.tcx
+                            .with_freevars(node_id, |freevars| {
+                                for (v, place) in freevars.iter().zip(places) {
+                                    match *place {
+                                        Operand::Copy(Place::Local(l))
+                                        | Operand::Move(Place::Local(l))
+                                            if local == l =>
+                                        {
+                                            debug!(
+                                                "find_closure_borrow_span: found captured local \
+                                                 {:?}",
+                                                l
+                                            );
+                                            return Some(v.span);
+                                        }
+                                        _ => {}
+                                    }
+                                }
+                                None
+                            }).map(|var_span| ClosureUse {
+                                args_span,
+                                var_span,
+                            }).unwrap_or(OtherUse(use_span))
+                    } else {
+                        OtherUse(use_span)
+                    };
+                }
+            }
+
+            if use_span != stmt.source_info.span {
+                break;
+            }
+        }
+
+        OtherUse(use_span)
+    }
+
+    /// Helper to retrieve span(s) of given borrow from the current MIR
+    /// representation
+    pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData) -> UseSpans {
+        let span = self.mir.source_info(borrow.reserve_location).span;
+        self.borrow_spans(span, borrow.reserve_location)
+    }
+}
index 4ba96f643b0ccaf1b9f66b2203ff2384f0122ba9..320d3a47203210e24611283560011f267f8b2e9b 100644 (file)
@@ -22,7 +22,7 @@
 use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
-use rustc::ty::{self, ParamEnv, TyCtxt};
+use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
 
 use rustc_errors::{Diagnostic, DiagnosticBuilder, Level};
 use rustc_data_structures::graph::dominators::Dominators;
@@ -331,6 +331,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     }
 
     if mbcx.errors_buffer.len() > 0 {
+        mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span());
+
         if tcx.migrate_borrowck() {
             match tcx.borrowck(def_id).signalled_any_error {
                 SignalledError::NoErrorsSeen => {
@@ -596,7 +598,12 @@ fn visit_terminator_entry(
                 // that is useful later.
                 let drop_place_ty = gcx.lift(&drop_place_ty).unwrap();
 
-                self.visit_terminator_drop(loc, term, flow_state, drop_place, drop_place_ty, span);
+                debug!("visit_terminator_drop \
+                        loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}",
+                       loc, term, drop_place, drop_place_ty, span);
+
+                self.visit_terminator_drop(
+                    loc, term, flow_state, drop_place, drop_place_ty, span, SeenTy(None));
             }
             TerminatorKind::DropAndReplace {
                 location: ref drop_place,
@@ -830,6 +837,35 @@ fn as_verb_in_past_tense(self) -> &'static str {
     }
 }
 
+/// A simple linked-list threaded up the stack of recursive calls in `visit_terminator_drop`.
+#[derive(Copy, Clone, Debug)]
+struct SeenTy<'a, 'gcx: 'a>(Option<(Ty<'gcx>, &'a SeenTy<'a, 'gcx>)>);
+
+impl<'a, 'gcx> SeenTy<'a, 'gcx> {
+    /// Return a new list with `ty` prepended to the front of `self`.
+    fn cons(&'a self, ty: Ty<'gcx>) -> Self {
+        SeenTy(Some((ty, self)))
+    }
+
+    /// True if and only if `ty` occurs on the linked list `self`.
+    fn have_seen(self, ty: Ty) -> bool {
+        let mut this = self.0;
+        loop {
+            match this {
+                None => return false,
+                Some((seen_ty, recur)) => {
+                    if seen_ty == ty {
+                        return true;
+                    } else {
+                        this = recur.0;
+                        continue;
+                    }
+                }
+            }
+        }
+    }
+}
+
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// Invokes `access_place` as appropriate for dropping the value
     /// at `drop_place`. Note that the *actual* `Drop` in the MIR is
@@ -845,14 +881,57 @@ fn visit_terminator_drop(
         drop_place: &Place<'tcx>,
         erased_drop_place_ty: ty::Ty<'gcx>,
         span: Span,
+        prev_seen: SeenTy<'_, 'gcx>,
     ) {
+        if prev_seen.have_seen(erased_drop_place_ty) {
+            // if we have directly seen the input ty `T`, then we must
+            // have had some *direct* ownership loop between `T` and
+            // some directly-owned (as in, actually traversed by
+            // recursive calls below) part that is also of type `T`.
+            //
+            // Note: in *all* such cases, the data in question cannot
+            // be constructed (nor destructed) in finite time/space.
+            //
+            // Proper examples, some of which are statically rejected:
+            //
+            // * `struct A { field: A, ... }`:
+            //   statically rejected as infinite size
+            //
+            // * `type B = (B, ...);`:
+            //   statically rejected as cyclic
+            //
+            // * `struct C { field: Box<C>, ... }`
+            // * `struct D { field: Box<(D, D)>, ... }`:
+            //   *accepted*, though impossible to construct
+            //
+            // Here is *NOT* an example:
+            // * `struct Z { field: Option<Box<Z>>, ... }`:
+            //   Here, the type is both representable in finite space (due to the boxed indirection)
+            //   and constructable in finite time (since the recursion can bottom out with `None`).
+            //   This is an obvious instance of something the compiler must accept.
+            //
+            // Since some of the above impossible cases like `C` and
+            // `D` are accepted by the compiler, we must take care not
+            // to infinite-loop while processing them. But since such
+            // cases cannot actually arise, it is sound for us to just
+            // skip them during drop. If the developer uses unsafe
+            // code to construct them, they should not be surprised by
+            // weird drop behavior in their resulting code.
+            debug!("visit_terminator_drop previously seen \
+                    erased_drop_place_ty: {:?} on prev_seen: {:?}; returning early.",
+                   erased_drop_place_ty, prev_seen);
+            return;
+        }
+
         let gcx = self.tcx.global_tcx();
         let drop_field = |mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
                           (index, field): (usize, ty::Ty<'gcx>)| {
             let field_ty = gcx.normalize_erasing_regions(mir.param_env, field);
             let place = drop_place.clone().field(Field::new(index), field_ty);
 
-            mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span);
+            debug!("visit_terminator_drop drop_field place: {:?} field_ty: {:?}", place, field_ty);
+            let seen = prev_seen.cons(erased_drop_place_ty);
+            mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span, seen);
         };
 
         match erased_drop_place_ty.sty {
@@ -897,13 +976,42 @@ fn visit_terminator_drop(
                     .enumerate()
                     .for_each(|field| drop_field(self, field));
             }
+
+            // #45696: special-case Box<T> by treating its dtor as
+            // only deep *across owned content*. Namely, we know
+            // dropping a box does not touch data behind any
+            // references it holds; if we were to instead fall into
+            // the base case below, we would have a Deep Write due to
+            // the box being `needs_drop`, and that Deep Write would
+            // touch `&mut` data in the box.
+            ty::TyAdt(def, _) if def.is_box() => {
+                // When/if we add a `&own T` type, this action would
+                // be like running the destructor of the `&own T`.
+                // (And the owner of backing storage referenced by the
+                // `&own T` would be responsible for deallocating that
+                // backing storage.)
+
+                // we model dropping any content owned by the box by
+                // recurring on box contents. This catches cases like
+                // `Box<Box<ScribbleWhenDropped<&mut T>>>`, while
+                // still restricting Write to *owned* content.
+                let ty = erased_drop_place_ty.boxed_ty();
+                let deref_place = drop_place.clone().deref();
+                debug!("visit_terminator_drop drop-box-content deref_place: {:?} ty: {:?}",
+                       deref_place, ty);
+                let seen = prev_seen.cons(erased_drop_place_ty);
+                self.visit_terminator_drop(
+                    loc, term, flow_state, &deref_place, ty, span, seen);
+            }
+
             _ => {
                 // We have now refined the type of the value being
                 // dropped (potentially) to just the type of a
                 // subfield; so check whether that field's type still
-                // "needs drop". If so, we assume that the destructor
-                // may access any data it likes (i.e., a Deep Write).
+                // "needs drop".
                 if erased_drop_place_ty.needs_drop(gcx, self.param_env) {
+                    // If so, we assume that the destructor may access
+                    // any data it likes (i.e., a Deep Write).
                     self.access_place(
                         ContextKind::Drop.new(loc),
                         (drop_place, span),
@@ -911,6 +1019,41 @@ fn visit_terminator_drop(
                         LocalMutationIsAllowed::Yes,
                         flow_state,
                     );
+                } else {
+                    // If there is no destructor, we still include a
+                    // *shallow* write.  This essentially ensures that
+                    // borrows of the memory directly at `drop_place`
+                    // cannot continue to be borrowed across the drop.
+                    //
+                    // If we were to use a Deep Write here, then any
+                    // `&mut T` that is reachable from `drop_place`
+                    // would get invalidated; fixing that is the
+                    // essence of resolving issue #45696.
+                    //
+                    // * Note: In the compiler today, doing a Deep
+                    //   Write here would not actually break
+                    //   anything beyond #45696; for example it does not
+                    //   break this example:
+                    //
+                    //   ```rust
+                    //   fn reborrow(x: &mut i32) -> &mut i32 { &mut *x }
+                    //   ```
+                    //
+                    //   Why? Because we do not schedule/emit
+                    //   `Drop(x)` in the MIR unless `x` needs drop in
+                    //   the first place.
+                    //
+                    // FIXME: Its possible this logic actually should
+                    // be attached to the `StorageDead` statement
+                    // rather than the `Drop`. See discussion on PR
+                    // #52782.
+                    self.access_place(
+                        ContextKind::Drop.new(loc),
+                        (drop_place, span),
+                        (Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
+                        LocalMutationIsAllowed::Yes,
+                        flow_state,
+                    );
                 }
             }
         }
@@ -1399,7 +1542,7 @@ fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span
         if borrow_of_local_data(&borrow.borrowed_place) {
             let err = self.tcx
                 .cannot_borrow_across_generator_yield(
-                    self.retrieve_borrow_span(borrow),
+                    self.retrieve_borrow_spans(borrow).var_or_use(),
                     yield_span,
                     Origin::Mir,
                 );
index 103f431d4bac9c9038b0eeb2a46c2b58153d75db..4d988fef450b8a527f5a5e341dca51b9a62e779d 100644 (file)
@@ -341,7 +341,8 @@ fn add_move_hints(
                 // another match arm
                 binds_to.sort();
                 binds_to.dedup();
-                for local in binds_to {
+                let mut multipart_suggestion = Vec::with_capacity(binds_to.len());
+                for (j, local) in binds_to.into_iter().enumerate() {
                     let bind_to = &self.mir.local_decls[local];
                     let binding_span = bind_to.source_info.span;
 
@@ -350,13 +351,15 @@ fn add_move_hints(
                         Mutability::Not => "ref",
                         Mutability::Mut => "ref mut",
                     };
+                    if j == 0 {
+                        err.span_label(binding_span, format!("data moved here"));
+                    } else {
+                        err.span_label(binding_span, format!("... and here"));
+                    }
                     match bind_to.name {
                         Some(name) => {
-                            err.span_suggestion(
-                                binding_span,
-                                "to prevent move, use ref or ref mut",
-                                format!("{} {:?}", ref_kind, name),
-                            );
+                            multipart_suggestion.push((binding_span,
+                                                       format!("{} {}", ref_kind, name)));
                         }
                         None => {
                             err.span_label(
@@ -366,6 +369,8 @@ fn add_move_hints(
                         }
                     }
                 }
+                err.multipart_suggestion("to prevent move, use ref or ref mut",
+                                         multipart_suggestion);
             }
             // Nothing to suggest.
             GroupedMoveError::OtherIllegalMove { .. } => (),
index 9a84daf53dbd46d4c5bbeebfef8a89c97bc85498..e8862320ddf3fcc83ce454ad0b92cae14743edd7 100644 (file)
@@ -160,7 +160,6 @@ pub(super) fn report_mutability_error(
         let act;
         let acted_on;
 
-
         let span = match error_access {
             AccessKind::Move => {
                 err = self.tcx
@@ -180,31 +179,23 @@ pub(super) fn report_mutability_error(
                 act = "borrow as mutable";
                 acted_on = "borrowed as mutable";
 
-                let closure_span = self.find_closure_span(span, location);
-                if let Some((args, var)) = closure_span {
-                    err = self.tcx.cannot_borrow_path_as_mutable_because(
-                        args,
-                        &item_msg,
-                        &reason,
-                        Origin::Mir,
-                    );
-                    err.span_label(
-                        var,
-                        format!(
-                            "mutable borrow occurs due to use of `{}` in closure",
-                            self.describe_place(access_place).unwrap(),
-                        ),
-                    );
-                    args
-                } else {
-                    err = self.tcx.cannot_borrow_path_as_mutable_because(
-                        span,
-                        &item_msg,
-                        &reason,
-                        Origin::Mir,
-                    );
-                    span
-                }
+                let borrow_spans = self.borrow_spans(span, location);
+                let borrow_span = borrow_spans.args_or_use();
+                err = self.tcx.cannot_borrow_path_as_mutable_because(
+                    borrow_span,
+                    &item_msg,
+                    &reason,
+                    Origin::Mir,
+                );
+                borrow_spans.var_span_label(
+                    &mut err,
+                    format!(
+                        "mutable borrow occurs due to use of `{}` in closure",
+                        // always Some() if the message is printed.
+                        self.describe_place(access_place).unwrap_or(String::new()),
+                    )
+                );
+                borrow_span
             }
         };
 
@@ -307,7 +298,7 @@ pub(super) fn report_mutability_error(
                 let local_decl = &self.mir.local_decls[*local];
                 let suggestion = match local_decl.is_user_variable.as_ref().unwrap() {
                     ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
-                        Some(suggest_ampmut_self(local_decl))
+                        Some(suggest_ampmut_self(self.tcx, local_decl))
                     }
 
                     ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
@@ -418,8 +409,22 @@ fn is_upvar(&self, place: &Place<'tcx>) -> bool {
     }
 }
 
-fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(local_decl: &mir::LocalDecl<'tcx>) -> (Span, String) {
-    (local_decl.source_info.span, "&mut self".to_string())
+fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    local_decl: &mir::LocalDecl<'tcx>,
+) -> (Span, String) {
+    let sp = local_decl.source_info.span;
+    (sp, match tcx.sess.codemap().span_to_snippet(sp) {
+        Ok(snippet) => {
+            let lt_pos = snippet.find('\'');
+            if let Some(lt_pos) = lt_pos {
+                format!("&{}mut self", &snippet[lt_pos..snippet.len() - 4])
+            } else {
+                "&mut self".to_string()
+            }
+        }
+        _ => "&mut self".to_string()
+    })
 }
 
 // When we want to suggest a user change a local variable to be a `&mut`, there
@@ -447,9 +452,15 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
     let locations = mir.find_assignments(local);
     if locations.len() > 0 {
         let assignment_rhs_span = mir.source_info(locations[0]).span;
-        let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span);
-        if let Ok(src) = snippet {
-            if src.starts_with('&') {
+        if let Ok(src) = tcx.sess.codemap().span_to_snippet(assignment_rhs_span) {
+            if let (true, Some(ws_pos)) = (
+                src.starts_with("&'"),
+                src.find(|c: char| -> bool { c.is_whitespace() }),
+            ) {
+                let lt_name = &src[1..ws_pos];
+                let ty = &src[ws_pos..];
+                return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
+            } else if src.starts_with('&') {
                 let borrowed_expr = src[1..].to_string();
                 return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
             }
@@ -466,13 +477,25 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
         None => local_decl.source_info.span,
     };
 
+    if let Ok(src) = tcx.sess.codemap().span_to_snippet(highlight_span) {
+        if let (true, Some(ws_pos)) = (
+            src.starts_with("&'"),
+            src.find(|c: char| -> bool { c.is_whitespace() }),
+        ) {
+            let lt_name = &src[1..ws_pos];
+            let ty = &src[ws_pos..];
+            return (highlight_span, format!("&{} mut{}", lt_name, ty));
+        }
+    }
+
     let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
     assert_eq!(ty_mut.mutbl, hir::MutImmutable);
-    if local_decl.ty.is_region_ptr() {
-        (highlight_span, format!("&mut {}", ty_mut.ty))
-    } else {
-        (highlight_span, format!("*mut {}", ty_mut.ty))
-    }
+    (highlight_span,
+     if local_decl.ty.is_region_ptr() {
+         format!("&mut {}", ty_mut.ty)
+     } else {
+         format!("*mut {}", ty_mut.ty)
+     })
 }
 
 fn is_closure_or_generator(ty: ty::Ty) -> bool {
diff --git a/src/librustc_mir/borrow_check/nll/escaping_locals.rs b/src/librustc_mir/borrow_check/nll/escaping_locals.rs
new file mode 100644 (file)
index 0000000..7e39f3d
--- /dev/null
@@ -0,0 +1,229 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Identify those variables whose entire value will eventually be
+//! returned from the fn via the RETURN_PLACE. As an optimization, we
+//! can skip computing liveness results for those variables. The idea
+//! is that the return type of the fn only ever contains free
+//! regions. Therefore, the types of those variables are going to
+//! ultimately be contrained to outlive those free regions -- since
+//! free regions are always live for the entire body, this implies
+//! that the liveness results are not important for those regions.
+//! This is most important in the "fns" that we create to represent static
+//! values, since those are often really quite large, and all regions in them
+//! will ultimately be constrained to be `'static`. Two examples:
+//!
+//! ```
+//! fn foo() -> &'static [u32] { &[] }
+//! static FOO: &[u32] = &[];
+//! ```
+//!
+//! In both these cases, the return value will only have static lifetime.
+//!
+//! NB: The simple logic here relies on the fact that outlives
+//! relations in our analysis don't have locations. Otherwise, we
+//! would have to restrict ourselves to values that are
+//! *unconditionally* returned (which would still cover the "big
+//! static value" case).
+//!
+//! The way that this code works is to use union-find -- we iterate
+//! over the MIR and union together two variables X and Y if all
+//! regions in the value of Y are going to be stored into X -- that
+//! is, if `typeof(X): 'a` requires that `typeof(Y): 'a`. This means
+//! that e.g. we can union together `x` and `y` if we have something
+//! like `x = (y, 22)`, but not something like `x = y.f` (since there
+//! may be regions in the type of `y` that do not appear in the field
+//! `f`).
+
+use rustc::mir::visit::Visitor;
+use rustc::mir::*;
+
+use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::unify as ut;
+
+crate struct EscapingLocals {
+    unification_table: ut::UnificationTable<ut::InPlace<AssignedLocal>>,
+}
+
+impl EscapingLocals {
+    crate fn compute(mir: &Mir<'tcx>) -> Self {
+        let mut visitor = GatherAssignedLocalsVisitor::new();
+        visitor.visit_mir(mir);
+
+        EscapingLocals {
+            unification_table: visitor.unification_table,
+        }
+    }
+
+    /// True if `local` is known to escape into static
+    /// memory.
+    crate fn escapes_into_return(&mut self, local: Local) -> bool {
+        let return_place = AssignedLocal::from(RETURN_PLACE);
+        let other_place = AssignedLocal::from(local);
+        self.unification_table.unioned(return_place, other_place)
+    }
+}
+
+/// The MIR visitor gathering the union-find of the locals used in
+/// assignments.
+struct GatherAssignedLocalsVisitor {
+    unification_table: ut::UnificationTable<ut::InPlace<AssignedLocal>>,
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+struct AssignedLocal(u32);
+
+impl ut::UnifyKey for AssignedLocal {
+    type Value = ();
+
+    fn index(&self) -> u32 {
+        self.0
+    }
+
+    fn from_index(i: u32) -> AssignedLocal {
+        AssignedLocal(i)
+    }
+
+    fn tag() -> &'static str {
+        "AssignedLocal"
+    }
+}
+
+impl From<Local> for AssignedLocal {
+    fn from(item: Local) -> Self {
+        // newtype_indexes use usize but are u32s.
+        assert!(item.index() < ::std::u32::MAX as usize);
+        AssignedLocal(item.index() as u32)
+    }
+}
+
+impl GatherAssignedLocalsVisitor {
+    fn new() -> Self {
+        Self {
+            unification_table: ut::UnificationTable::new(),
+        }
+    }
+
+    fn union_locals_if_needed(&mut self, lvalue: Option<Local>, rvalue: Option<Local>) {
+        if let Some(lvalue) = lvalue {
+            if let Some(rvalue) = rvalue {
+                if lvalue != rvalue {
+                    debug!("EscapingLocals: union {:?} and {:?}", lvalue, rvalue);
+                    self.unification_table
+                        .union(AssignedLocal::from(lvalue), AssignedLocal::from(rvalue));
+                }
+            }
+        }
+    }
+}
+
+// Returns the potential `Local` associated to this `Place` or `PlaceProjection`
+fn find_local_in_place(place: &Place) -> Option<Local> {
+    match place {
+        Place::Local(local) => Some(*local),
+
+        // If you do e.g. `x = a.f` then only *part* of the type of
+        // `a` escapes into `x` (the part contained in `f`); if `a`'s
+        // type has regions that don't appear in `f`, those might not
+        // escape.
+        Place::Projection(..) => None,
+
+        Place::Static { .. } | Place::Promoted { .. } => None,
+    }
+}
+
+// Returns the potential `Local` in this `Operand`.
+fn find_local_in_operand(op: &Operand) -> Option<Local> {
+    // Conservatively check a subset of `Operand`s we know our
+    // benchmarks track, for example `html5ever`.
+    match op {
+        Operand::Copy(place) | Operand::Move(place) => find_local_in_place(place),
+        Operand::Constant(_) => None,
+    }
+}
+
+impl Visitor<'tcx> for GatherAssignedLocalsVisitor {
+    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
+        // We need as many union-find keys as there are locals
+        for _ in 0..mir.local_decls.len() {
+            self.unification_table.new_key(());
+        }
+
+        self.super_mir(mir);
+    }
+
+    fn visit_assign(
+        &mut self,
+        block: BasicBlock,
+        place: &Place<'tcx>,
+        rvalue: &Rvalue<'tcx>,
+        location: Location,
+    ) {
+        let local = find_local_in_place(place);
+
+        // Find those cases where there is a `Place` consumed by
+        // `rvalue` and we know that all regions in its type will be
+        // incorporated into `place`, the `Place` we are assigning to.
+        match rvalue {
+            // `x = y` is the simplest possible case.
+            Rvalue::Use(op) => self.union_locals_if_needed(local, find_local_in_operand(op)),
+
+            // `X = &'r P` -- the type of `X` will be `&'r T_P`, where
+            // `T_P` is the type of `P`.
+            Rvalue::Ref(_, _, place) => {
+                // Special case: if you have `X = &*Y` (or `X = &**Y`
+                // etc), then the outlives relationships will ensure
+                // that all regions in `Y` are constrained by regions
+                // in `X` -- this is because the lifetimes of the
+                // references we deref through are required to outlive
+                // the borrow lifetime `'r` (which appears in `X`).
+                //
+                // (We don't actually need to check the type of `Y`:
+                // since `ProjectionElem::Deref` represents a built-in
+                // deref and not an overloaded deref, if the thing we
+                // deref through is not a reference, then it must be a
+                // `Box` or `*const`, in which case it contains no
+                // references.)
+                let mut place_ref = place;
+                while let Place::Projection(proj) = place_ref {
+                    if let ProjectionElem::Deref = proj.elem {
+                        place_ref = &proj.base;
+                    } else {
+                        break;
+                    }
+                }
+
+                self.union_locals_if_needed(local, find_local_in_place(place_ref))
+            }
+
+            Rvalue::Cast(kind, op, _) => match kind {
+                CastKind::Unsize => {
+                    // Casting a `&[T; N]` to `&[T]` or `&Foo` to `&Trait` --
+                    // in both cases, no regions are "lost".
+                    self.union_locals_if_needed(local, find_local_in_operand(op))
+                }
+                _ => (),
+            },
+
+            // Constructing an aggregate like `(x,)` or `Foo { x }`
+            // includes the full type of `x`.
+            Rvalue::Aggregate(_, ops) => {
+                for rvalue in ops.iter().map(find_local_in_operand) {
+                    self.union_locals_if_needed(local, rvalue);
+                }
+            }
+
+            // For other things, be conservative and do not union.
+            _ => (),
+        };
+
+        self.super_assign(block, place, rvalue, location);
+    }
+}
index cdb0351d9a8f08ca7f9faf95fb2e6a12205c7b51..5098b24adc367507e756324a682e14f7234122ec 100644 (file)
@@ -11,7 +11,7 @@
 use borrow_check::borrow_set::BorrowData;
 use borrow_check::nll::region_infer::Cause;
 use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
-use rustc::mir::Place;
+use rustc::mir::{Location, Place, TerminatorKind};
 use rustc_errors::DiagnosticBuilder;
 
 mod find_use;
@@ -62,11 +62,24 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
         );
 
         match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
-            Some(Cause::LiveVar(_local, location)) => {
-                err.span_label(
-                    mir.source_info(location).span,
-                    "borrow later used here".to_string(),
-                );
+            Some(Cause::LiveVar(local, location)) => {
+                let span = mir.source_info(location).span;
+                let spans = self.move_spans(&Place::Local(local), location)
+                    .or_else(|| self.borrow_spans(span, location));
+                let message = if self.is_borrow_location_in_loop(context.loc) {
+                    if spans.for_closure() {
+                        "borrow captured here by closure in later iteration of loop"
+                    } else {
+                        "borrow used here in later iteration of loop"
+                    }
+                } else {
+                    if spans.for_closure() {
+                        "borrow later captured here by closure"
+                    } else {
+                        "borrow later used here"
+                    }
+                };
+                err.span_label(spans.var_or_use(), message);
             }
 
             Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
@@ -107,4 +120,76 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
             }
         }
     }
+
+    /// Check if a borrow location is within a loop.
+    fn is_borrow_location_in_loop(
+        &self,
+        borrow_location: Location,
+    ) -> bool {
+        let mut visited_locations = Vec::new();
+        let mut pending_locations = vec![ borrow_location ];
+        debug!("is_in_loop: borrow_location={:?}", borrow_location);
+
+        while let Some(location) = pending_locations.pop() {
+            debug!("is_in_loop: location={:?} pending_locations={:?} visited_locations={:?}",
+                   location, pending_locations, visited_locations);
+            if location == borrow_location && visited_locations.contains(&borrow_location) {
+                // We've managed to return to where we started (and this isn't the start of the
+                // search).
+                debug!("is_in_loop: found!");
+                return true;
+            }
+
+            // Skip locations we've been.
+            if visited_locations.contains(&location) { continue; }
+
+            let block = &self.mir.basic_blocks()[location.block];
+            if location.statement_index ==  block.statements.len() {
+                // Add start location of the next blocks to pending locations.
+                match block.terminator().kind {
+                    TerminatorKind::Goto { target } => {
+                        pending_locations.push(target.start_location());
+                    },
+                    TerminatorKind::SwitchInt { ref targets, .. } => {
+                        for target in targets {
+                            pending_locations.push(target.start_location());
+                        }
+                    },
+                    TerminatorKind::Drop { target, unwind, .. } |
+                    TerminatorKind::DropAndReplace { target, unwind, .. } |
+                    TerminatorKind::Assert { target, cleanup: unwind, .. } |
+                    TerminatorKind::Yield { resume: target, drop: unwind, .. } |
+                    TerminatorKind::FalseUnwind { real_target: target, unwind, .. } => {
+                        pending_locations.push(target.start_location());
+                        if let Some(unwind) = unwind {
+                            pending_locations.push(unwind.start_location());
+                        }
+                    },
+                    TerminatorKind::Call { ref destination, cleanup, .. } => {
+                        if let Some((_, destination)) = destination {
+                            pending_locations.push(destination.start_location());
+                        }
+                        if let Some(cleanup) = cleanup {
+                            pending_locations.push(cleanup.start_location());
+                        }
+                    },
+                    TerminatorKind::FalseEdges { real_target, ref imaginary_targets, .. } => {
+                        pending_locations.push(real_target.start_location());
+                        for target in imaginary_targets {
+                            pending_locations.push(target.start_location());
+                        }
+                    },
+                    _ => {},
+                }
+            } else {
+                // Add the next statement to pending locations.
+                pending_locations.push(location.successor_within_block());
+            }
+
+            // Keep track of where we have visited.
+            visited_locations.push(location);
+        }
+
+        false
+    }
 }
index cbd9c9a4e1a85368906de6d91bd210585a731c7b..d018a9277d83420158a50b2f0c14333f3d89d6ef 100644 (file)
 //! liveness code so that it only operates over variables with regions in their
 //! types, instead of all variables.
 
+use borrow_check::nll::escaping_locals::EscapingLocals;
+use rustc::mir::{Local, Mir};
 use rustc::ty::TypeFoldable;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc::mir::{Mir, Local};
 use util::liveness::LiveVariableMap;
 
 use rustc_data_structures::indexed_vec::Idx;
 crate struct NllLivenessMap {
     /// For each local variable, contains either None (if the type has no regions)
     /// or Some(i) with a suitable index.
-    pub from_local: IndexVec<Local, Option<LocalWithRegion>>,
-    /// For each LocalWithRegion, maps back to the original Local index.
-    pub to_local: IndexVec<LocalWithRegion, Local>,
+    from_local: IndexVec<Local, Option<LocalWithRegion>>,
 
+    /// For each LocalWithRegion, maps back to the original Local index.
+    to_local: IndexVec<LocalWithRegion, Local>,
 }
 
 impl LiveVariableMap for NllLivenessMap {
-
     fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
         self.from_local[local]
     }
@@ -55,21 +55,43 @@ fn num_variables(&self) -> usize {
 impl NllLivenessMap {
     /// Iterates over the variables in Mir and assigns each Local whose type contains
     /// regions a LocalWithRegion index. Returns a map for converting back and forth.
-    pub fn compute(mir: &Mir) -> Self {
+    crate fn compute(mir: &Mir<'tcx>) -> Self {
+        let mut escaping_locals = EscapingLocals::compute(mir);
+
         let mut to_local = IndexVec::default();
-        let from_local: IndexVec<Local,Option<_>> = mir
+        let mut escapes_into_return = 0;
+        let mut no_regions = 0;
+        let from_local: IndexVec<Local, Option<_>> = mir
             .local_decls
             .iter_enumerated()
             .map(|(local, local_decl)| {
-                if local_decl.ty.has_free_regions() {
-                    Some(to_local.push(local))
+                if escaping_locals.escapes_into_return(local) {
+                    // If the local escapes into the return value,
+                    // then the return value will force all of the
+                    // regions in its type to outlive free regions
+                    // (e.g., `'static`) and hence liveness is not
+                    // needed. This is particularly important for big
+                    // statics.
+                    escapes_into_return += 1;
+                    None
+                } else if local_decl.ty.has_free_regions() {
+                    let l = to_local.push(local);
+                    debug!("liveness_map: {:?} = {:?}", local, l);
+                    Some(l)
+                } else {
+                    no_regions += 1;
+                    None
                 }
-                    else {
-                        None
-                    }
             }).collect();
 
-        Self { from_local, to_local }
+        debug!("liveness_map: {} variables need liveness", to_local.len());
+        debug!("liveness_map: {} escapes into return", escapes_into_return);
+        debug!("liveness_map: {} no regions", no_regions);
+
+        Self {
+            from_local,
+            to_local,
+        }
     }
 }
 
index 973568a67f030e8fdf04c89d45a8e59cfc5376c2..44ed6b7676c0c61e18e517f8eaf1dc1cf554ca39 100644 (file)
@@ -39,7 +39,9 @@
 use util as mir_util;
 use util::pretty::{self, ALIGN};
 
+mod constraints;
 mod constraint_generation;
+mod escaping_locals;
 pub mod explain_borrow;
 mod facts;
 mod invalidation;
@@ -49,8 +51,6 @@
 mod universal_regions;
 crate mod liveness_map;
 
-mod constraints;
-
 use self::facts::AllFacts;
 use self::region_infer::RegionInferenceContext;
 use self::universal_regions::UniversalRegions;
@@ -120,6 +120,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         location_table,
         borrow_set,
         &liveness,
+        &liveness_map,
         &mut all_facts,
         flow_inits,
         move_data,
@@ -205,6 +206,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     dump_mir_results(
         infcx,
         &liveness,
+        &liveness_map,
         MirSource::item(def_id),
         &mir,
         &regioncx,
@@ -221,6 +223,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
 fn dump_mir_results<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     liveness: &LivenessResults<LocalWithRegion>,
+    liveness_map: &NllLivenessMap,
     source: MirSource,
     mir: &Mir<'tcx>,
     regioncx: &RegionInferenceContext,
@@ -230,8 +233,6 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
         return;
     }
 
-    let map = &NllLivenessMap::compute(mir);
-
     let regular_liveness_per_location: FxHashMap<_, _> = mir
         .basic_blocks()
         .indices()
@@ -239,7 +240,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
             let mut results = vec![];
             liveness
                 .regular
-                .simulate_block(&mir, bb, map, |location, local_set| {
+                .simulate_block(&mir, bb, liveness_map, |location, local_set| {
                     results.push((location, local_set.clone()));
                 });
             results
@@ -253,7 +254,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
             let mut results = vec![];
             liveness
                 .drop
-                .simulate_block(&mir, bb, map, |location, local_set| {
+                .simulate_block(&mir, bb, liveness_map, |location, local_set| {
                     results.push((location, local_set.clone()));
                 });
             results
index 8505d8e1ef39c4cca816f36fa3e7398b54f7c74b..79165276430d34b2a20dcd8eb575036bb50d44b9 100644 (file)
 use rustc::infer::InferCtxt;
 use rustc::mir::Mir;
 use rustc::ty::subst::{Substs, UnpackedKind};
-use rustc::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
 use rustc::util::ppaux::with_highlight_region;
 use rustc_errors::DiagnosticBuilder;
-use syntax::ast::Name;
+use syntax::ast::{Name, DUMMY_NODE_ID};
 use syntax::symbol::keywords;
 use syntax_pos::symbol::InternedString;
 
@@ -90,14 +90,21 @@ fn give_name_from_error_region(
         diag: &mut DiagnosticBuilder<'_>,
     ) -> Option<InternedString> {
         let error_region = self.to_error_region(fr)?;
+
         debug!("give_region_a_name: error_region = {:?}", error_region);
         match error_region {
-            ty::ReEarlyBound(ebr) => Some(ebr.name),
+            ty::ReEarlyBound(ebr) => {
+                self.highlight_named_span(tcx, error_region, &ebr.name, diag);
+                Some(ebr.name)
+            },
 
             ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()),
 
             ty::ReFree(free_region) => match free_region.bound_region {
-                ty::BoundRegion::BrNamed(_, name) => Some(name),
+                ty::BoundRegion::BrNamed(_, name) => {
+                    self.highlight_named_span(tcx, error_region, &name, diag);
+                    Some(name)
+                },
 
                 ty::BoundRegion::BrEnv => {
                     let closure_span = tcx.hir.span_if_local(mir_def_id).unwrap();
@@ -123,6 +130,45 @@ fn give_name_from_error_region(
         }
     }
 
+    /// Highlight a named span to provide context for error messages that
+    /// mention that span, for example:
+    ///
+    /// ```
+    ///  |
+    ///  | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+    ///  |                --  -- lifetime `'b` defined here
+    ///  |                |
+    ///  |                lifetime `'a` defined here
+    ///  |
+    ///  |     with_signature(cell, t, |cell, t| require(cell, t));
+    ///  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must
+    ///  |                                                         outlive `'a`
+    /// ```
+    fn highlight_named_span(
+        &self,
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        error_region: &RegionKind,
+        name: &InternedString,
+        diag: &mut DiagnosticBuilder<'_>,
+    ) {
+        let cm = tcx.sess.codemap();
+
+        let scope = error_region.free_region_binding_scope(tcx);
+        let node = tcx.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID);
+
+        let mut sp = cm.def_span(tcx.hir.span(node));
+        if let Some(param) = tcx.hir.get_generics(scope).and_then(|generics| {
+            generics.get_named(name)
+        }) {
+            sp = param.span;
+        }
+
+        diag.span_label(
+            sp,
+            format!("lifetime `{}` defined here", name),
+        );
+    }
+
     /// Find an argument that contains `fr` and label it with a fully
     /// elaborated type, returning something like `'1`. Result looks
     /// like:
index 2b9307db59af9feb3821760f2c52f059845d3d39..d02f54dc4b87df4feb35bac7279b1c82526c4cad 100644 (file)
@@ -37,6 +37,7 @@ pub(super) fn generate<'gcx, 'tcx>(
     cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
     mir: &Mir<'tcx>,
     liveness: &LivenessResults<LocalWithRegion>,
+    liveness_map: &NllLivenessMap,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) {
@@ -44,10 +45,10 @@ pub(super) fn generate<'gcx, 'tcx>(
         cx,
         mir,
         liveness,
+        liveness_map,
         flow_inits,
         move_data,
         drop_data: FxHashMap(),
-        map: &NllLivenessMap::compute(mir),
     };
 
     for bb in mir.basic_blocks().indices() {
@@ -65,10 +66,10 @@ struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx>
     cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>,
     mir: &'gen Mir<'tcx>,
     liveness: &'gen LivenessResults<LocalWithRegion>,
+    liveness_map: &'gen NllLivenessMap,
     flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>,
     move_data: &'gen MoveData<'tcx>,
     drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>,
-    map: &'gen NllLivenessMap,
 }
 
 struct DropData<'tcx> {
@@ -86,9 +87,9 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
 
         self.liveness
             .regular
-            .simulate_block(self.mir, bb, self.map, |location, live_locals| {
+            .simulate_block(self.mir, bb, self.liveness_map, |location, live_locals| {
                 for live_local in live_locals.iter() {
-                    let local = self.map.from_live_var(live_local);
+                    let local = self.liveness_map.from_live_var(live_local);
                     let live_local_ty = self.mir.local_decls[local].ty;
                     Self::push_type_live_constraint(&mut self.cx, live_local_ty, location);
                 }
@@ -97,7 +98,7 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
         let mut all_live_locals: Vec<(Location, Vec<LocalWithRegion>)> = vec![];
         self.liveness
             .drop
-            .simulate_block(self.mir, bb, self.map, |location, live_locals| {
+            .simulate_block(self.mir, bb, self.liveness_map, |location, live_locals| {
                 all_live_locals.push((location, live_locals.iter().collect()));
             });
         debug!(
@@ -124,7 +125,7 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
                     });
                 }
 
-                let local = self.map.from_live_var(live_local);
+                let local = self.liveness_map.from_live_var(live_local);
                 let mpi = self.move_data.rev_lookup.find_local(local);
                 if let Some(initialized_child) = self.flow_inits.has_any_child_of(mpi) {
                     debug!(
@@ -133,7 +134,7 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
                         self.move_data.move_paths[initialized_child]
                     );
 
-                    let local = self.map.from_live_var(live_local);
+                    let local = self.liveness_map.from_live_var(live_local);
                     let live_local_ty = self.mir.local_decls[local].ty;
                     self.add_drop_live_constraint(live_local, live_local_ty, location);
                 }
index a18e2368bf724d55b81f5f5afba76711e8d149d3..15afc6c52bf2b34eec323282f19e110bad45aec2 100644 (file)
 use borrow_check::location::LocationTable;
 use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
-use borrow_check::nll::region_infer::values::{RegionValueElements, LivenessValues};
+use borrow_check::nll::liveness_map::NllLivenessMap;
+use borrow_check::nll::region_infer::values::{LivenessValues, RegionValueElements};
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
-use borrow_check::nll::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
+use borrow_check::nll::type_check::free_region_relations::{
+    CreateResult, UniversalRegionRelations,
+};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use borrow_check::nll::LocalWithRegion;
 use borrow_check::nll::ToRegionVid;
@@ -116,6 +119,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     location_table: &LocationTable,
     borrow_set: &BorrowSet<'tcx>,
     liveness: &LivenessResults<LocalWithRegion>,
+    liveness_map: &NllLivenessMap,
     all_facts: &mut Option<AllFacts>,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
@@ -166,7 +170,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
             Some(&mut borrowck_context),
             Some(errors_buffer),
             |cx| {
-                liveness::generate(cx, mir, liveness, flow_inits, move_data);
+                liveness::generate(cx, mir, liveness, liveness_map, flow_inits, move_data);
                 cx.equate_inputs_and_outputs(
                     mir,
                     mir_def_id,
index c44af0036547966e4f390cca6334c72425ef2225..640ae31d45b349db89028614c438daca19eca80e 100644 (file)
@@ -329,6 +329,13 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
         }
         (Place::Promoted(p1), Place::Promoted(p2)) => {
             if p1.0 == p2.0 {
+                if let ty::TyArray(_, size) = p1.1.sty {
+                    if size.unwrap_usize(tcx) == 0 {
+                        // Ignore conflicts with promoted [T; 0].
+                        debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
+                        return Overlap::Disjoint;
+                    }
+                }
                 // the same promoted - base case, equal
                 debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
                 Overlap::EqualOrDisjoint
index a509ec08a142e4cb93ac1dae54b53fe6bd117040..6b6ec749bcbe6efd1124d6f529264564a4aab661 100644 (file)
@@ -18,7 +18,7 @@
 use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
 use build::scope::{CachedBlock, DropKind};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc::ty::{self, Ty};
 use rustc::mir::*;
 use rustc::hir;
@@ -496,7 +496,7 @@ enum TestKind<'tcx> {
     // test the branches of enum
     Switch {
         adt_def: &'tcx ty::AdtDef,
-        variants: BitVector<usize>,
+        variants: BitArray<usize>,
     },
 
     // test the branches of enum
@@ -1213,11 +1213,17 @@ fn declare_binding(&mut self,
         let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() {
             let mut vals_for_guard = Vec::with_capacity(num_patterns);
             for _ in 0..num_patterns {
-                let val_for_guard_idx =  self.local_decls.push(local.clone());
+                let val_for_guard_idx = self.local_decls.push(LocalDecl {
+                    // This variable isn't mutated but has a name, so has to be
+                    // immutable to avoid the unused mut lint.
+                    mutability: Mutability::Not,
+                    ..local.clone()
+                });
                 vals_for_guard.push(val_for_guard_idx);
             }
             let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
-                mutability,
+                // See previous comment.
+                mutability: Mutability::Not,
                 ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
                 name: Some(name),
                 source_info,
index f8bfb5b48ba99fdc18ec18087d1a7c703d1d4a2f..7106e02284da3888cd219b61d17fe23ce5076bb6 100644 (file)
@@ -19,7 +19,7 @@
 use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc::ty::{self, Ty};
 use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
@@ -38,7 +38,7 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
                     span: match_pair.pattern.span,
                     kind: TestKind::Switch {
                         adt_def: adt_def.clone(),
-                        variants: BitVector::new(adt_def.variants.len()),
+                        variants: BitArray::new(adt_def.variants.len()),
                     },
                 }
             }
@@ -149,7 +149,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
     pub fn add_variants_to_switch<'pat>(&mut self,
                                         test_place: &Place<'tcx>,
                                         candidate: &Candidate<'pat, 'tcx>,
-                                        variants: &mut BitVector<usize>)
+                                        variants: &mut BitArray<usize>)
                                         -> bool
     {
         let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
index 96f4c6b60f511648627799e684ecbacc91a95fcc..c8c41c13b0fbb684fbaa8967689f6fb12f9a3508 100644 (file)
@@ -15,9 +15,9 @@
 use dataflow::BitDenotation;
 
 /// This calculates if any part of a MIR local could have previously been borrowed.
-/// This means that once a local has been borrowed, its bit will always be set
-/// from that point and onwards, even if the borrow ends. You could also think of this
-/// as computing the lifetimes of infinite borrows.
+/// This means that once a local has been borrowed, its bit will be set
+/// from that point and onwards, until we see a StorageDead statement for the local,
+/// at which points there is no memory associated with the local, so it cannot be borrowed.
 /// This is used to compute which locals are live during a yield expression for
 /// immovable generators.
 #[derive(Copy, Clone)]
@@ -50,9 +50,17 @@ fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
     fn statement_effect(&self,
                         sets: &mut BlockSets<Local>,
                         loc: Location) {
+        let stmt = &self.mir[loc.block].statements[loc.statement_index];
+
         BorrowedLocalsVisitor {
             sets,
-        }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc);
+        }.visit_statement(loc.block, stmt, loc);
+
+        // StorageDead invalidates all borrows and raw pointers to a local
+        match stmt.kind {
+            StatementKind::StorageDead(l) => sets.kill(&l),
+            _ => (),
+        }
     }
 
     fn terminator_effect(&self,
index 4a7225c3a76d1a93e718dd31c5551003480ab8fd..70148fc91760443bb6d31b18de8988fa5eb6ac21 100644 (file)
@@ -151,14 +151,14 @@ pub fn const_eval_literal(
 
         let trunc = |n| {
             let param_ty = self.param_env.and(self.tcx.lift_to_global(&ty).unwrap());
-            let bit_width = self.tcx.layout_of(param_ty).unwrap().size.bits();
-            trace!("trunc {} with size {} and shift {}", n, bit_width, 128 - bit_width);
-            let shift = 128 - bit_width;
+            let width = self.tcx.layout_of(param_ty).unwrap().size;
+            trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
+            let shift = 128 - width.bits();
             let result = (n << shift) >> shift;
             trace!("trunc result: {}", result);
             ConstValue::Scalar(Scalar::Bits {
                 bits: result,
-                defined: bit_width as u8,
+                size: width.bytes() as u8,
             })
         };
 
@@ -168,7 +168,7 @@ pub fn const_eval_literal(
                 let s = s.as_str();
                 let id = self.tcx.allocate_bytes(s.as_bytes());
                 let value = Scalar::Ptr(id.into()).to_value_with_len(s.len() as u64, self.tcx);
-                ConstValue::from_byval_value(value)
+                ConstValue::from_byval_value(value).unwrap()
             },
             LitKind::ByteStr(ref data) => {
                 let id = self.tcx.allocate_bytes(data);
@@ -176,7 +176,7 @@ pub fn const_eval_literal(
             },
             LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits {
                 bits: n as u128,
-                defined: 8,
+                size: 1,
             }),
             LitKind::Int(n, _) if neg => {
                 let n = n as i128;
@@ -194,14 +194,8 @@ pub fn const_eval_literal(
                 };
                 parse_float(n, fty)
             }
-            LitKind::Bool(b) => ConstValue::Scalar(Scalar::Bits {
-                bits: b as u128,
-                defined: 8,
-            }),
-            LitKind::Char(c) => ConstValue::Scalar(Scalar::Bits {
-                bits: c as u128,
-                defined: 32,
-            }),
+            LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
+            LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
         };
         ty::Const::from_const_value(self.tcx, lit, ty)
     }
index 53511c1c127dd3a608813cf38a92c0f4cd58ed92..d614131c526837623dbcae21965fb572b157206b 100644 (file)
@@ -19,7 +19,7 @@
 use interpret::{const_val_field, const_variant_index, self};
 
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
-use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, Value};
+use rustc::mir::interpret::{Scalar, GlobalId, ConstValue};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -1080,8 +1080,9 @@ pub fn compare_const_vals<'a, 'tcx>(
                 l.partial_cmp(&r)
             },
             ty::TyInt(_) => {
-                let a = interpret::sign_extend(tcx, a, ty.value).expect("layout error for TyInt");
-                let b = interpret::sign_extend(tcx, b, ty.value).expect("layout error for TyInt");
+                let layout = tcx.layout_of(ty).ok()?;
+                let a = interpret::sign_extend(a, layout);
+                let b = interpret::sign_extend(b, layout);
                 Some((a as i128).cmp(&(b as i128)))
             },
             _ => Some(a.cmp(&b)),
@@ -1090,17 +1091,24 @@ pub fn compare_const_vals<'a, 'tcx>(
 
     if let ty::TyRef(_, rty, _) = ty.value.sty {
         if let ty::TyStr = rty.sty {
-            match (a.to_byval_value(), b.to_byval_value()) {
+            match (a.val, b.val) {
                 (
-                    Some(Value::ScalarPair(
+                    ConstValue::ScalarPair(
                         Scalar::Ptr(ptr_a),
                         len_a,
-                    )),
-                    Some(Value::ScalarPair(
+                    ),
+                    ConstValue::ScalarPair(
                         Scalar::Ptr(ptr_b),
                         len_b,
-                    ))
+                    ),
                 ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
+                    let len_a = len_a.unwrap_or_err().ok();
+                    let len_b = len_b.unwrap_or_err().ok();
+                    if len_a.is_none() || len_b.is_none() {
+                        tcx.sess.struct_err("str slice len is undef").delay_as_bug();
+                    }
+                    let len_a = len_a?;
+                    let len_b = len_b?;
                     if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
                         if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
                             if len_a == len_b {
@@ -1142,7 +1150,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
             let s = s.as_str();
             let id = tcx.allocate_bytes(s.as_bytes());
             let value = Scalar::Ptr(id.into()).to_value_with_len(s.len() as u64, tcx);
-            ConstValue::from_byval_value(value)
+            ConstValue::from_byval_value(value).unwrap()
         },
         LitKind::ByteStr(ref data) => {
             let id = tcx.allocate_bytes(data);
@@ -1150,7 +1158,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
         },
         LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits {
             bits: n as u128,
-            defined: 8,
+            size: 1,
         }),
         LitKind::Int(n, _) => {
             enum Int {
@@ -1188,10 +1196,10 @@ enum Int {
                 Int::Signed(IntTy::I128)| Int::Unsigned(UintTy::U128) => n,
                 _ => bug!(),
             };
-            let defined = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size.bits() as u8;
+            let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size.bytes() as u8;
             ConstValue::Scalar(Scalar::Bits {
                 bits: n,
-                defined,
+                size,
             })
         },
         LitKind::Float(n, fty) => {
@@ -1204,14 +1212,8 @@ enum Int {
             };
             parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
         }
-        LitKind::Bool(b) => ConstValue::Scalar(Scalar::Bits {
-            bits: b as u128,
-            defined: 8,
-        }),
-        LitKind::Char(c) => ConstValue::Scalar(Scalar::Bits {
-            bits: c as u128,
-            defined: 32,
-        }),
+        LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
+        LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
     };
     Ok(ty::Const::from_const_value(tcx, lit, ty))
 }
@@ -1224,7 +1226,7 @@ pub fn parse_float<'tcx>(
     let num = num.as_str();
     use rustc_apfloat::ieee::{Single, Double};
     use rustc_apfloat::Float;
-    let (bits, defined) = match fty {
+    let (bits, size) = match fty {
         ast::FloatTy::F32 => {
             num.parse::<f32>().map_err(|_| ())?;
             let mut f = num.parse::<Single>().unwrap_or_else(|e| {
@@ -1233,7 +1235,7 @@ pub fn parse_float<'tcx>(
             if neg {
                 f = -f;
             }
-            (f.to_bits(), 32)
+            (f.to_bits(), 4)
         }
         ast::FloatTy::F64 => {
             num.parse::<f64>().map_err(|_| ())?;
@@ -1243,9 +1245,9 @@ pub fn parse_float<'tcx>(
             if neg {
                 f = -f;
             }
-            (f.to_bits(), 64)
+            (f.to_bits(), 8)
         }
     };
 
-    Ok(ConstValue::Scalar(Scalar::Bits { bits, defined }))
+    Ok(ConstValue::Scalar(Scalar::Bits { bits, size }))
 }
index 7bcf4ef6588d53d9335a767b077016d5b798b817..4e705254331a2f08a2d1eec5c724912ae5e58b71 100644 (file)
@@ -1,5 +1,5 @@
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, LayoutOf};
+use rustc::ty::layout::{self, LayoutOf, TyLayout};
 use syntax::ast::{FloatTy, IntTy, UintTy};
 
 use rustc_apfloat::ieee::{Single, Double};
@@ -18,11 +18,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
         dest_ty: Ty<'tcx>,
         dest: Place,
     ) -> EvalResult<'tcx> {
+        let src_layout = self.layout_of(src.ty)?;
+        let dst_layout = self.layout_of(dest_ty)?;
         use rustc::mir::CastKind::*;
         match kind {
             Unsize => {
-                let src_layout = self.layout_of(src.ty)?;
-                let dst_layout = self.layout_of(dest_ty)?;
                 self.unsize_into(src.value, src_layout, dest, dst_layout)?;
             }
 
@@ -57,16 +57,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                                 let discr_val = def
                                     .discriminant_for_variant(*self.tcx, index)
                                     .val;
-                                let defined = self
-                                    .layout_of(dest_ty)
-                                    .unwrap()
-                                    .size
-                                    .bits() as u8;
                                 return self.write_scalar(
                                     dest,
                                     Scalar::Bits {
                                         bits: discr_val,
-                                        defined,
+                                        size: dst_layout.size.bytes() as u8,
                                     },
                                     dest_ty);
                             }
@@ -76,9 +71,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                     }
 
                     let src_val = self.value_to_scalar(src)?;
-                    let dest_val = self.cast_scalar(src_val, src.ty, dest_ty)?;
+                    let dest_val = self.cast_scalar(src_val, src_layout, dst_layout)?;
                     let valty = ValTy {
-                        value: Value::Scalar(dest_val),
+                        value: Value::Scalar(dest_val.into()),
                         ty: dest_ty,
                     };
                     self.write_value(valty, dest)?;
@@ -100,7 +95,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                         ).ok_or_else(|| EvalErrorKind::TooGeneric.into());
                         let fn_ptr = self.memory.create_fn_alloc(instance?);
                         let valty = ValTy {
-                            value: Value::Scalar(fn_ptr.into()),
+                            value: Value::Scalar(Scalar::Ptr(fn_ptr.into()).into()),
                             ty: dest_ty,
                         };
                         self.write_value(valty, dest)?;
@@ -136,7 +131,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                         );
                         let fn_ptr = self.memory.create_fn_alloc(instance);
                         let valty = ValTy {
-                            value: Value::Scalar(fn_ptr.into()),
+                            value: Value::Scalar(Scalar::Ptr(fn_ptr.into()).into()),
                             ty: dest_ty,
                         };
                         self.write_value(valty, dest)?;
@@ -151,20 +146,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
     pub(super) fn cast_scalar(
         &self,
         val: Scalar,
-        src_ty: Ty<'tcx>,
-        dest_ty: Ty<'tcx>,
+        src_layout: TyLayout<'tcx>,
+        dest_layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, Scalar> {
         use rustc::ty::TypeVariants::*;
-        trace!("Casting {:?}: {:?} to {:?}", val, src_ty, dest_ty);
+        trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
 
         match val {
-            Scalar::Bits { defined: 0, .. } => Ok(val),
-            Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_ty),
-            Scalar::Bits { bits, .. } => {
-                // TODO(oli-obk): check defined bits here
-                match src_ty.sty {
-                    TyFloat(fty) => self.cast_from_float(bits, fty, dest_ty),
-                    _ => self.cast_from_int(bits, src_ty, dest_ty),
+            Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
+            Scalar::Bits { bits, size } => {
+                assert_eq!(size as u64, src_layout.size.bytes());
+                match src_layout.ty.sty {
+                    TyFloat(fty) => self.cast_from_float(bits, fty, dest_layout.ty),
+                    _ => self.cast_from_int(bits, src_layout, dest_layout),
                 }
             }
         }
@@ -173,56 +167,58 @@ pub(super) fn cast_scalar(
     fn cast_from_int(
         &self,
         v: u128,
-        src_ty: Ty<'tcx>,
-        dest_ty: Ty<'tcx>,
+        src_layout: TyLayout<'tcx>,
+        dest_layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, Scalar> {
-        let signed = self.layout_of(src_ty)?.abi.is_signed();
+        let signed = src_layout.abi.is_signed();
         let v = if signed {
-            self.sign_extend(v, src_ty)?
+            self.sign_extend(v, src_layout)
         } else {
             v
         };
-        trace!("cast_from_int: {}, {}, {}", v, src_ty, dest_ty);
+        trace!("cast_from_int: {}, {}, {}", v, src_layout.ty, dest_layout.ty);
         use rustc::ty::TypeVariants::*;
-        match dest_ty.sty {
+        match dest_layout.ty.sty {
             TyInt(_) | TyUint(_) => {
-                let v = self.truncate(v, dest_ty)?;
+                let v = self.truncate(v, dest_layout);
                 Ok(Scalar::Bits {
                     bits: v,
-                    defined: self.layout_of(dest_ty).unwrap().size.bits() as u8,
+                    size: dest_layout.size.bytes() as u8,
                 })
             }
 
             TyFloat(FloatTy::F32) if signed => Ok(Scalar::Bits {
                 bits: Single::from_i128(v as i128).value.to_bits(),
-                defined: 32,
+                size: 4,
             }),
             TyFloat(FloatTy::F64) if signed => Ok(Scalar::Bits {
                 bits: Double::from_i128(v as i128).value.to_bits(),
-                defined: 64,
+                size: 8,
             }),
             TyFloat(FloatTy::F32) => Ok(Scalar::Bits {
                 bits: Single::from_u128(v).value.to_bits(),
-                defined: 32,
+                size: 4,
             }),
             TyFloat(FloatTy::F64) => Ok(Scalar::Bits {
                 bits: Double::from_u128(v).value.to_bits(),
-                defined: 64,
+                size: 8,
             }),
 
-            TyChar if v as u8 as u128 == v => Ok(Scalar::Bits { bits: v, defined: 32 }),
-            TyChar => err!(InvalidChar(v)),
+            TyChar => {
+                assert_eq!(v as u8 as u128, v);
+                Ok(Scalar::Bits { bits: v, size: 4 })
+            },
 
             // No alignment check needed for raw pointers.  But we have to truncate to target ptr size.
             TyRawPtr(_) => {
                 Ok(Scalar::Bits {
                     bits: self.memory.truncate_to_ptr(v).0 as u128,
-                    defined: self.memory.pointer_size().bits() as u8,
+                    size: self.memory.pointer_size().bytes() as u8,
                 })
             },
 
             // Casts to bool are not permitted by rustc, no need to handle them here.
-            _ => err!(Unimplemented(format!("int to {:?} cast", dest_ty))),
+            _ => err!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))),
         }
     }
 
@@ -236,11 +232,11 @@ fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalRe
                 match fty {
                     FloatTy::F32 => Ok(Scalar::Bits {
                         bits: Single::from_bits(bits).to_u128(width).value,
-                        defined: width as u8,
+                        size: (width / 8) as u8,
                     }),
                     FloatTy::F64 => Ok(Scalar::Bits {
                         bits: Double::from_bits(bits).to_u128(width).value,
-                        defined: width as u8,
+                        size: (width / 8) as u8,
                     }),
                 }
             },
@@ -250,11 +246,11 @@ fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalRe
                 match fty {
                     FloatTy::F32 => Ok(Scalar::Bits {
                         bits: Single::from_bits(bits).to_i128(width).value as u128,
-                        defined: width as u8,
+                        size: (width / 8) as u8,
                     }),
                     FloatTy::F64 => Ok(Scalar::Bits {
                         bits: Double::from_bits(bits).to_i128(width).value as u128,
-                        defined: width as u8,
+                        size: (width / 8) as u8,
                     }),
                 }
             },
@@ -262,24 +258,24 @@ fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalRe
             TyFloat(FloatTy::F32) if fty == FloatTy::F64 => {
                 Ok(Scalar::Bits {
                     bits: Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
-                    defined: 32,
+                    size: 4,
                 })
             },
             // f32 -> f64
             TyFloat(FloatTy::F64) if fty == FloatTy::F32 => {
                 Ok(Scalar::Bits {
                     bits: Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
-                    defined: 64,
+                    size: 8,
                 })
             },
             // identity cast
             TyFloat(FloatTy:: F64) => Ok(Scalar::Bits {
                 bits,
-                defined: 64,
+                size: 8,
             }),
             TyFloat(FloatTy:: F32) => Ok(Scalar::Bits {
                 bits,
-                defined: 32,
+                size: 4,
             }),
             _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
         }
index 873fef75bb9ebf666d41be4b0729fc6b9da0e067..9d66a0b396b640fe7d3498aa75dc7b9caedb9bc2 100644 (file)
@@ -2,11 +2,12 @@
 use std::error::Error;
 
 use rustc::hir;
-use rustc::mir::interpret::{ConstEvalErr};
+use rustc::mir::interpret::{ConstEvalErr, ScalarMaybeUndef};
 use rustc::mir;
 use rustc::ty::{self, TyCtxt, Ty, Instance};
 use rustc::ty::layout::{self, LayoutOf, Primitive, TyLayout};
 use rustc::ty::subst::Subst;
+use rustc_data_structures::indexed_vec::IndexVec;
 
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
@@ -28,13 +29,16 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
     let param_env = tcx.param_env(instance.def_id());
     let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
     // insert a stack frame so any queries have the correct substs
-    ecx.push_stack_frame(
+    ecx.stack.push(super::eval_context::Frame {
+        block: mir::START_BLOCK,
+        locals: IndexVec::new(),
         instance,
         span,
         mir,
-        Place::undef(),
-        StackPopCleanup::None,
-    )?;
+        return_place: Place::undef(),
+        return_to_block: StackPopCleanup::None,
+        stmt: 0,
+    });
     Ok(ecx)
 }
 
@@ -72,48 +76,30 @@ pub fn eval_promoted<'a, 'mir, 'tcx>(
 pub fn value_to_const_value<'tcx>(
     ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
     val: Value,
-    ty: Ty<'tcx>,
-) -> &'tcx ty::Const<'tcx> {
-    let layout = ecx.layout_of(ty).unwrap();
+    layout: TyLayout<'tcx>,
+) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> {
     match (val, &layout.abi) {
-        (Value::Scalar(Scalar::Bits { defined: 0, ..}), _) if layout.is_zst() => {},
+        (Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { size: 0, ..})), _) if layout.is_zst() => {},
         (Value::ByRef(..), _) |
         (Value::Scalar(_), &layout::Abi::Scalar(_)) |
         (Value::ScalarPair(..), &layout::Abi::ScalarPair(..)) => {},
         _ => bug!("bad value/layout combo: {:#?}, {:#?}", val, layout),
     }
-    let val = (|| {
-        match val {
-            Value::Scalar(val) => Ok(ConstValue::Scalar(val)),
-            Value::ScalarPair(a, b) => Ok(ConstValue::ScalarPair(a, b)),
-            Value::ByRef(ptr, align) => {
-                let ptr = ptr.to_ptr().unwrap();
-                let alloc = ecx.memory.get(ptr.alloc_id)?;
-                assert!(alloc.align.abi() >= align.abi());
-                assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes());
-                let mut alloc = alloc.clone();
-                alloc.align = align;
-                let alloc = ecx.tcx.intern_const_alloc(alloc);
-                Ok(ConstValue::ByRef(alloc, ptr.offset))
-            }
-        }
-    })();
-    match val {
-        Ok(val) => ty::Const::from_const_value(ecx.tcx.tcx, val, ty),
-        Err(err) => {
-            let (frames, span) = ecx.generate_stacktrace(None);
-            let err = ConstEvalErr {
-                span,
-                error: err,
-                stacktrace: frames,
-            };
-            err.report_as_error(
-                ecx.tcx,
-                "failed to convert Value to ConstValue, this is a bug",
-            );
-            span_bug!(span, "miri error occured when converting Value to ConstValue")
+    let val = match val {
+        Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?),
+        Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b),
+        Value::ByRef(ptr, align) => {
+            let ptr = ptr.to_ptr().unwrap();
+            let alloc = ecx.memory.get(ptr.alloc_id)?;
+            assert!(alloc.align.abi() >= align.abi());
+            assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes());
+            let mut alloc = alloc.clone();
+            alloc.align = align;
+            let alloc = ecx.tcx.intern_const_alloc(alloc);
+            ConstValue::ByRef(alloc, ptr.offset)
         }
-    }
+    };
+    Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, layout.ty))
 }
 
 fn eval_body_and_ecx<'a, 'mir, 'tcx>(
@@ -307,7 +293,7 @@ fn call_intrinsic<'a>(
                 let elem_align = ecx.layout_of(elem_ty)?.align.abi();
                 let align_val = Scalar::Bits {
                     bits: elem_align as u128,
-                    defined: dest_layout.size.bits() as u8,
+                    size: dest_layout.size.bytes() as u8,
                 };
                 ecx.write_scalar(dest, align_val, dest_layout.ty)?;
             }
@@ -317,7 +303,7 @@ fn call_intrinsic<'a>(
                 let size = ecx.layout_of(ty)?.size.bytes() as u128;
                 let size_val = Scalar::Bits {
                     bits: size,
-                    defined: dest_layout.size.bits() as u8,
+                    size: dest_layout.size.bytes() as u8,
                 };
                 ecx.write_scalar(dest, size_val, dest_layout.ty)?;
             }
@@ -327,7 +313,7 @@ fn call_intrinsic<'a>(
                 let type_id = ecx.tcx.type_id_hash(ty) as u128;
                 let id_val = Scalar::Bits {
                     bits: type_id,
-                    defined: dest_layout.size.bits() as u8,
+                    size: dest_layout.size.bytes() as u8,
                 };
                 ecx.write_scalar(dest, id_val, dest_layout.ty)?;
             }
@@ -437,7 +423,7 @@ pub fn const_val_field<'a, 'tcx>(
         let place = ecx.allocate_place_for_value(value, layout, variant)?;
         let (place, layout) = ecx.place_field(place, field, layout)?;
         let (ptr, align) = place.to_ptr_align();
-        let mut new_value = Value::ByRef(ptr, align);
+        let mut new_value = Value::ByRef(ptr.unwrap_or_err()?, align);
         new_value = ecx.try_read_by_ref(new_value, layout.ty)?;
         use rustc_data_structures::indexed_vec::Idx;
         match (value, new_value) {
@@ -451,7 +437,7 @@ pub fn const_val_field<'a, 'tcx>(
             ),
             _ => {},
         }
-        Ok(value_to_const_value(&ecx, new_value, layout.ty))
+        value_to_const_value(&ecx, new_value, layout)
     })();
     result.map_err(|err| {
         let (trace, span) = ecx.generate_stacktrace(None);
@@ -481,7 +467,7 @@ pub fn const_variant_index<'a, 'tcx>(
         },
         Value::ByRef(ptr, align) => (ptr, align),
     };
-    let place = Place::from_scalar_ptr(ptr, align);
+    let place = Place::from_scalar_ptr(ptr.into(), align);
     ecx.read_discriminant_as_variant_index(place, layout)
 }
 
@@ -552,7 +538,7 @@ pub fn const_eval_provider<'a, 'tcx>(
         if tcx.is_static(def_id).is_none() && cid.promoted.is_none() {
             val = ecx.try_read_by_ref(val, layout.ty)?;
         }
-        Ok(value_to_const_value(&ecx, val, layout.ty))
+        value_to_const_value(&ecx, val, layout)
     }).map_err(|err| {
         let (trace, span) = ecx.generate_stacktrace(None);
         let err = ConstEvalErr {
@@ -562,6 +548,9 @@ pub fn const_eval_provider<'a, 'tcx>(
         };
         if tcx.is_static(def_id).is_some() {
             err.report_as_error(ecx.tcx, "could not evaluate static initializer");
+            if tcx.sess.err_count() == 0 {
+                span_bug!(span, "static eval failure didn't emit an error: {:#?}", err);
+            }
         }
         err.into()
     })
@@ -572,11 +561,11 @@ fn numeric_intrinsic<'tcx>(
     bits: u128,
     kind: Primitive,
 ) -> EvalResult<'tcx, Scalar> {
-    let defined = match kind {
-        Primitive::Int(integer, _) => integer.size().bits() as u8,
+    let size = match kind {
+        Primitive::Int(integer, _) => integer.size(),
         _ => bug!("invalid `{}` argument: {:?}", name, bits),
     };
-    let extra = 128 - defined as u128;
+    let extra = 128 - size.bits() as u128;
     let bits_out = match name {
         "ctpop" => bits.count_ones() as u128,
         "ctlz" => bits.leading_zeros() as u128 - extra,
@@ -584,5 +573,5 @@ fn numeric_intrinsic<'tcx>(
         "bswap" => (bits << extra).swap_bytes(),
         _ => bug!("not a numeric intrinsic: {}", name),
     };
-    Ok(Scalar::Bits { bits: bits_out, defined })
+    Ok(Scalar::Bits { bits: bits_out, size: size.bytes() as u8 })
 }
index c6c1a1d1ebb22b8e43c43f278c75204d8ea10fd8..52305be5facef18c2b762c7ffe754320921c53d7 100644 (file)
@@ -15,6 +15,7 @@
 use rustc::mir::interpret::{
     GlobalId, Value, Scalar, FrameInfo, AllocType,
     EvalResult, EvalErrorKind, Pointer, ConstValue,
+    ScalarMaybeUndef,
 };
 
 use syntax::codemap::{self, Span};
@@ -105,9 +106,7 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     /// `[return_ptr, arguments..., variables..., temporaries...]`. The locals are stored as `Option<Value>`s.
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
-    ///
-    /// Before being initialized, arguments are `Value::Scalar(Scalar::undef())` and other locals are `None`.
-    pub locals: IndexVec<mir::Local, Option<Value>>,
+    pub locals: IndexVec<mir::Local, LocalValue>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -120,6 +119,21 @@ pub struct Frame<'mir, 'tcx: 'mir> {
     pub stmt: usize,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub enum LocalValue {
+    Dead,
+    Live(Value),
+}
+
+impl LocalValue {
+    pub fn access(self) -> EvalResult<'static, Value> {
+        match self {
+            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Live(val) => Ok(val),
+        }
+    }
+}
+
 impl<'mir, 'tcx: 'mir> Eq for Frame<'mir, 'tcx> {}
 
 impl<'mir, 'tcx: 'mir> PartialEq for Frame<'mir, 'tcx> {
@@ -395,8 +409,8 @@ pub fn const_to_value(
                 let id = self.memory.allocate_value(alloc.clone(), MemoryKind::Stack)?;
                 Ok(Value::ByRef(Pointer::new(id, offset).into(), alloc.align))
             },
-            ConstValue::ScalarPair(a, b) => Ok(Value::ScalarPair(a, b)),
-            ConstValue::Scalar(val) => Ok(Value::Scalar(val)),
+            ConstValue::ScalarPair(a, b) => Ok(Value::ScalarPair(a.into(), b.into())),
+            ConstValue::Scalar(val) => Ok(Value::Scalar(val.into())),
         }
     }
 
@@ -452,7 +466,7 @@ pub fn monomorphize(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx>
     /// Note that the value does not matter if the type is sized. For unsized types,
     /// the value has to be a fat pointer, and we only care about the "extra" data in it.
     pub fn size_and_align_of_dst(
-        &mut self,
+        &self,
         ty: Ty<'tcx>,
         value: Value,
     ) -> EvalResult<'tcx, (Size, Align)> {
@@ -480,7 +494,7 @@ pub fn size_and_align_of_dst(
 
                     // Recurse to get the size of the dynamically sized field (must be
                     // the last field).
-                    let field_ty = layout.field(&self, layout.fields.count() - 1)?.ty;
+                    let field_ty = layout.field(self, layout.fields.count() - 1)?.ty;
                     let (unsized_size, unsized_align) =
                         self.size_and_align_of_dst(field_ty, value)?;
 
@@ -518,7 +532,7 @@ pub fn size_and_align_of_dst(
                 }
 
                 ty::TySlice(_) | ty::TyStr => {
-                    let (elem_size, align) = layout.field(&self, 0)?.size_and_align();
+                    let (elem_size, align) = layout.field(self, 0)?.size_and_align();
                     let (_, len) = self.into_slice(value)?;
                     Ok((elem_size * len, align))
                 }
@@ -538,8 +552,26 @@ pub fn push_stack_frame(
     ) -> EvalResult<'tcx> {
         ::log_settings::settings().indentation += 1;
 
-        let locals = if mir.local_decls.len() > 1 {
-            let mut locals = IndexVec::from_elem(Some(Value::Scalar(Scalar::undef())), &mir.local_decls);
+        // first push a stack frame so we have access to the local substs
+        self.stack.push(Frame {
+            mir,
+            block: mir::START_BLOCK,
+            return_to_block,
+            return_place,
+            // empty local array, we fill it in below, after we are inside the stack frame and
+            // all methods actually know about the frame
+            locals: IndexVec::new(),
+            span,
+            instance,
+            stmt: 0,
+        });
+
+        // don't allocate at all for trivial constants
+        if mir.local_decls.len() > 1 {
+            let mut locals = IndexVec::from_elem(LocalValue::Dead, &mir.local_decls);
+            for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) {
+                *local = LocalValue::Live(self.init_value(decl.ty)?);
+            }
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
                 Some(Def::Static(..)) | Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {},
@@ -550,29 +582,15 @@ pub fn push_stack_frame(
                             use rustc::mir::StatementKind::{StorageDead, StorageLive};
                             match stmt.kind {
                                 StorageLive(local) |
-                                StorageDead(local) => locals[local] = None,
+                                StorageDead(local) => locals[local] = LocalValue::Dead,
                                 _ => {}
                             }
                         }
                     }
                 },
             }
-            locals
-        } else {
-            // don't allocate at all for trivial constants
-            IndexVec::new()
-        };
-
-        self.stack.push(Frame {
-            mir,
-            block: mir::START_BLOCK,
-            return_to_block,
-            return_place,
-            locals,
-            span,
-            instance,
-            stmt: 0,
-        });
+            self.frame_mut().locals = locals;
+        }
 
         self.memory.cur_frame = self.cur_frame();
 
@@ -598,7 +616,7 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
                 if let Place::Ptr { ptr, .. } = frame.return_place {
                     // FIXME: to_ptr()? might be too extreme here, static zsts might reach this under certain conditions
                     self.memory.mark_static_initialized(
-                        ptr.to_ptr()?.alloc_id,
+                        ptr.unwrap_or_err()?.to_ptr()?.alloc_id,
                         mutable,
                     )?
                 } else {
@@ -616,8 +634,9 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
         Ok(())
     }
 
-    pub fn deallocate_local(&mut self, local: Option<Value>) -> EvalResult<'tcx> {
-        if let Some(Value::ByRef(ptr, _align)) = local {
+    pub fn deallocate_local(&mut self, local: LocalValue) -> EvalResult<'tcx> {
+        // FIXME: should we tell the user that there was a local which was never written to?
+        if let LocalValue::Live(Value::ByRef(ptr, _align)) = local {
             trace!("deallocating local");
             let ptr = ptr.to_ptr()?;
             self.memory.dump_alloc(ptr.alloc_id);
@@ -637,6 +656,7 @@ pub(super) fn eval_rvalue_into_place(
     ) -> EvalResult<'tcx> {
         let dest = self.eval_place(place)?;
         let dest_ty = self.place_ty(place);
+        let dest_layout = self.layout_of(dest_ty)?;
 
         use rustc::mir::Rvalue::*;
         match *rvalue {
@@ -675,7 +695,7 @@ pub(super) fn eval_rvalue_into_place(
 
             UnaryOp(un_op, ref operand) => {
                 let val = self.eval_operand_to_scalar(operand)?;
-                let val = self.unary_op(un_op, val, dest_ty)?;
+                let val = self.unary_op(un_op, val, dest_layout)?;
                 self.write_scalar(
                     dest,
                     val,
@@ -724,6 +744,7 @@ pub(super) fn eval_rvalue_into_place(
                 let (dest, dest_align) = self.force_allocation(dest)?.to_ptr_align();
 
                 if length > 0 {
+                    let dest = dest.unwrap_or_err()?;
                     //write the first value
                     self.write_value_to_ptr(value, dest, dest_align, elem_ty)?;
 
@@ -739,12 +760,12 @@ pub(super) fn eval_rvalue_into_place(
                 let src = self.eval_place(place)?;
                 let ty = self.place_ty(place);
                 let (_, len) = src.elem_ty_and_len(ty, self.tcx.tcx);
-                let defined = self.memory.pointer_size().bits() as u8;
+                let size = self.memory.pointer_size().bytes() as u8;
                 self.write_scalar(
                     dest,
                     Scalar::Bits {
                         bits: len as u128,
-                        defined,
+                        size,
                     },
                     dest_ty,
                 )?;
@@ -757,7 +778,7 @@ pub(super) fn eval_rvalue_into_place(
                 let (ptr, _align, extra) = self.force_allocation(src)?.to_ptr_align_extra();
 
                 let val = match extra {
-                    PlaceExtra::None => ptr.to_value(),
+                    PlaceExtra::None => Value::Scalar(ptr),
                     PlaceExtra::Length(len) => ptr.to_value_with_len(len, self.tcx.tcx),
                     PlaceExtra::Vtable(vtable) => ptr.to_value_with_vtable(vtable),
                     PlaceExtra::DowncastVariant(..) => {
@@ -781,12 +802,12 @@ pub(super) fn eval_rvalue_into_place(
                 let layout = self.layout_of(ty)?;
                 assert!(!layout.is_unsized(),
                         "SizeOf nullary MIR operator called for unsized type");
-                let defined = self.memory.pointer_size().bits() as u8;
+                let size = self.memory.pointer_size().bytes() as u8;
                 self.write_scalar(
                     dest,
                     Scalar::Bits {
                         bits: layout.size.bytes() as u128,
-                        defined,
+                        size,
                     },
                     dest_ty,
                 )?;
@@ -803,10 +824,10 @@ pub(super) fn eval_rvalue_into_place(
                 let layout = self.layout_of(ty)?;
                 let place = self.eval_place(place)?;
                 let discr_val = self.read_discriminant_value(place, layout)?;
-                let defined = self.layout_of(dest_ty).unwrap().size.bits() as u8;
+                let size = self.layout_of(dest_ty).unwrap().size.bytes() as u8;
                 self.write_scalar(dest, Scalar::Bits {
                     bits: discr_val,
-                    defined,
+                    size,
                 }, dest_ty)?;
             }
         }
@@ -957,10 +978,8 @@ pub fn read_discriminant_value(
                         assert!(variants_start == variants_end);
                         dataful_variant as u128
                     },
-                    Scalar::Bits { bits: raw_discr, defined } => {
-                        if defined < discr.size.bits() as u8 {
-                            return err!(ReadUndefBytes);
-                        }
+                    Scalar::Bits { bits: raw_discr, size } => {
+                        assert_eq!(size as u64, discr.size.bytes());
                         let discr = raw_discr.wrapping_sub(niche_start)
                             .wrapping_add(variants_start);
                         if variants_start <= discr && discr <= variants_end {
@@ -1002,14 +1021,14 @@ pub fn write_discriminant_value(
                 // raw discriminants for enums are isize or bigger during
                 // their computation, but the in-memory tag is the smallest possible
                 // representation
-                let size = tag.value.size(self.tcx.tcx).bits();
-                let shift = 128 - size;
+                let size = tag.value.size(self.tcx.tcx);
+                let shift = 128 - size.bits();
                 let discr_val = (discr_val << shift) >> shift;
 
                 let (discr_dest, tag) = self.place_field(dest, mir::Field::new(0), layout)?;
                 self.write_scalar(discr_dest, Scalar::Bits {
                     bits: discr_val,
-                    defined: size as u8,
+                    size: size.bytes() as u8,
                 }, tag.ty)?;
             }
             layout::Variants::NicheFilling {
@@ -1025,7 +1044,7 @@ pub fn write_discriminant_value(
                         .wrapping_add(niche_start);
                     self.write_scalar(niche_dest, Scalar::Bits {
                         bits: niche_value,
-                        defined: niche.size.bits() as u8,
+                        size: niche.size.bytes() as u8,
                     }, niche.ty)?;
                 }
             }
@@ -1063,7 +1082,7 @@ pub fn allocate_place_for_value(
             },
         };
         Ok(Place::Ptr {
-            ptr,
+            ptr: ptr.into(),
             align,
             extra: variant.map_or(PlaceExtra::None, PlaceExtra::DowncastVariant),
         })
@@ -1072,22 +1091,22 @@ pub fn allocate_place_for_value(
     pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
         let new_place = match place {
             Place::Local { frame, local } => {
-                match self.stack[frame].locals[local] {
-                    None => return err!(DeadLocal),
-                    Some(Value::ByRef(ptr, align)) => {
+                match self.stack[frame].locals[local].access()? {
+                    Value::ByRef(ptr, align) => {
                         Place::Ptr {
-                            ptr,
+                            ptr: ptr.into(),
                             align,
                             extra: PlaceExtra::None,
                         }
                     }
-                    Some(val) => {
+                    val => {
                         let ty = self.stack[frame].mir.local_decls[local].ty;
                         let ty = self.monomorphize(ty, self.stack[frame].instance.substs);
                         let layout = self.layout_of(ty)?;
                         let ptr = self.alloc_ptr(layout)?;
                         self.stack[frame].locals[local] =
-                            Some(Value::ByRef(ptr.into(), layout.align)); // it stays live
+                            LocalValue::Live(Value::ByRef(ptr.into(), layout.align)); // it stays live
+
                         let place = Place::from_ptr(ptr, layout.align);
                         self.write_value(ValTy { value: val, ty }, place)?;
                         place
@@ -1120,7 +1139,7 @@ pub fn value_to_scalar(
         match self.follow_by_ref_value(value, ty)? {
             Value::ByRef { .. } => bug!("follow_by_ref_value can't result in `ByRef`"),
 
-            Value::Scalar(scalar) => Ok(scalar),
+            Value::Scalar(scalar) => scalar.unwrap_or_err(),
 
             Value::ScalarPair(..) => bug!("value_to_scalar can't work with fat pointers"),
         }
@@ -1137,11 +1156,11 @@ pub fn write_ptr(&mut self, dest: Place, val: Scalar, dest_ty: Ty<'tcx>) -> Eval
     pub fn write_scalar(
         &mut self,
         dest: Place,
-        val: Scalar,
+        val: impl Into<ScalarMaybeUndef>,
         dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx> {
         let valty = ValTy {
-            value: Value::Scalar(val),
+            value: Value::Scalar(val.into()),
             ty: dest_ty,
         };
         self.write_value(valty, dest)
@@ -1160,15 +1179,15 @@ pub fn write_value(
         match dest {
             Place::Ptr { ptr, align, extra } => {
                 assert_eq!(extra, PlaceExtra::None);
-                self.write_value_to_ptr(src_val, ptr, align, dest_ty)
+                self.write_value_to_ptr(src_val, ptr.unwrap_or_err()?, align, dest_ty)
             }
 
             Place::Local { frame, local } => {
-                let dest = self.stack[frame].get_local(local)?;
+                let old_val = self.stack[frame].locals[local].access()?;
                 self.write_value_possibly_by_val(
                     src_val,
                     |this, val| this.stack[frame].set_local(local, val),
-                    dest,
+                    old_val,
                     dest_ty,
                 )
             }
@@ -1183,6 +1202,7 @@ fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
         old_dest_val: Value,
         dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx> {
+        // FIXME: this should be a layout check, not underlying value
         if let Value::ByRef(dest_ptr, align) = old_dest_val {
             // If the value is already `ByRef` (that is, backed by an `Allocation`),
             // then we must write the new value into this allocation, because there may be
@@ -1239,12 +1259,9 @@ pub fn write_value_to_ptr(
                         layout::Primitive::Int(_, signed) => signed,
                         _ => false,
                     },
-                    _ => match scalar {
-                        Scalar::Bits { defined: 0, .. } => false,
-                        _ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout),
-                    }
+                    _ => false,
                 };
-                self.memory.write_scalar(dest, dest_align, scalar, layout.size, signed)
+                self.memory.write_scalar(dest, dest_align, scalar, layout.size, layout.align, signed)
             }
             Value::ScalarPair(a_val, b_val) => {
                 trace!("write_value_to_ptr valpair: {:#?}", layout);
@@ -1253,12 +1270,13 @@ pub fn write_value_to_ptr(
                     _ => bug!("write_value_to_ptr: invalid ScalarPair layout: {:#?}", layout)
                 };
                 let (a_size, b_size) = (a.size(&self), b.size(&self));
+                let (a_align, b_align) = (a.align(&self), b.align(&self));
                 let a_ptr = dest;
-                let b_offset = a_size.abi_align(b.align(&self));
+                let b_offset = a_size.abi_align(b_align);
                 let b_ptr = dest.ptr_offset(b_offset, &self)?.into();
                 // TODO: What about signedess?
-                self.memory.write_scalar(a_ptr, dest_align, a_val, a_size, false)?;
-                self.memory.write_scalar(b_ptr, dest_align, b_val, b_size, false)
+                self.memory.write_scalar(a_ptr, dest_align, a_val, a_size, a_align, false)?;
+                self.memory.write_scalar(b_ptr, dest_align, b_val, b_size, b_align, false)
             }
         }
     }
@@ -1271,38 +1289,9 @@ pub fn read_value(&self, ptr: Scalar, align: Align, ty: Ty<'tcx>) -> EvalResult<
         }
     }
 
-    pub(crate) fn read_ptr(
-        &self,
-        ptr: Pointer,
-        ptr_align: Align,
-        pointee_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx, Value> {
-        let ptr_size = self.memory.pointer_size();
-        let p: Scalar = self.memory.read_ptr_sized(ptr, ptr_align)?.into();
-        if self.type_is_sized(pointee_ty) {
-            Ok(p.to_value())
-        } else {
-            trace!("reading fat pointer extra of type {}", pointee_ty);
-            let extra = ptr.offset(ptr_size, self)?;
-            match self.tcx.struct_tail(pointee_ty).sty {
-                ty::TyDynamic(..) => Ok(p.to_value_with_vtable(
-                    self.memory.read_ptr_sized(extra, ptr_align)?.to_ptr()?,
-                )),
-                ty::TySlice(..) | ty::TyStr => {
-                    let len = self
-                        .memory
-                        .read_ptr_sized(extra, ptr_align)?
-                        .to_bits(ptr_size)?;
-                    Ok(p.to_value_with_len(len as u64, self.tcx.tcx))
-                },
-                _ => bug!("unsized scalar ptr read from {:?}", pointee_ty),
-            }
-        }
-    }
-
     fn validate_scalar(
         &self,
-        value: Scalar,
+        value: ScalarMaybeUndef,
         size: Size,
         scalar: &layout::Scalar,
         path: &str,
@@ -1311,8 +1300,16 @@ fn validate_scalar(
         trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty);
         let (lo, hi) = scalar.valid_range.clone().into_inner();
 
-        let (bits, defined) = match value {
-            Scalar::Bits { bits, defined } => (bits, defined),
+        let value = match value {
+            ScalarMaybeUndef::Scalar(scalar) => scalar,
+            ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
+        };
+
+        let bits = match value {
+            Scalar::Bits { bits, size: value_size } => {
+                assert_eq!(value_size as u64, size.bytes());
+                bits
+            },
             Scalar::Ptr(_) => {
                 let ptr_size = self.memory.pointer_size();
                 let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
@@ -1346,7 +1343,7 @@ fn validate_scalar(
         // has no special checks for chars
         match ty.sty {
             ty::TyChar => {
-                assert_eq!(size.bytes(), 4);
+                debug_assert_eq!(size.bytes(), 4);
                 if ::std::char::from_u32(bits as u32).is_none() {
                     return err!(InvalidChar(bits));
                 }
@@ -1355,32 +1352,26 @@ fn validate_scalar(
         }
 
         use std::ops::RangeInclusive;
-        let in_range = |bound: RangeInclusive<u128>| {
-            defined as u64 >= size.bits() && bound.contains(&bits)
-        };
+        let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
         if lo > hi {
             if in_range(0..=hi) || in_range(lo..=u128::max_value()) {
                 Ok(())
-            } else if defined as u64 >= size.bits() {
+            } else {
                 validation_failure!(
                     bits,
                     path,
                     format!("something in the range {:?} or {:?}", ..=hi, lo..)
                 )
-            } else {
-                validation_failure!("undefined bytes", path)
             }
         } else {
             if in_range(scalar.valid_range.clone()) {
                 Ok(())
-            } else if defined as u64 >= size.bits() {
+            } else {
                 validation_failure!(
                     bits,
                     path,
                     format!("something in the range {:?}", scalar.valid_range)
                 )
-            } else {
-                validation_failure!("undefined bytes", path)
             }
         }
     }
@@ -1410,10 +1401,10 @@ pub fn validate_ptr_target(
                     mir::Field::new(0),
                     layout,
                 )?;
-                let tag_value = self.value_to_scalar(ValTy {
-                    value: tag_value,
-                    ty: tag_layout.ty,
-                })?;
+                let tag_value = match self.follow_by_ref_value(tag_value, tag_layout.ty)? {
+                    Value::Scalar(val) => val,
+                    _ => bug!("tag must be scalar"),
+                };
                 let path = format!("{}.TAG", path);
                 self.validate_scalar(tag_value, size, tag, &path, tag_layout.ty)?;
                 let variant_index = self.read_discriminant_as_variant_index(
@@ -1440,7 +1431,7 @@ pub fn validate_ptr_target(
                         self.validate_scalar(value, size, scalar, &path, layout.ty)?;
                         if scalar.value == Primitive::Pointer {
                             // ignore integer pointers, we can't reason about the final hardware
-                            if let Scalar::Ptr(ptr) = value {
+                            if let Scalar::Ptr(ptr) = value.unwrap_or_err()? {
                                 let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
                                 if let Some(AllocType::Static(did)) = alloc_kind {
                                     // statics from other crates are already checked
@@ -1534,7 +1525,7 @@ pub fn try_read_value(&self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> Eva
         self.memory.check_align(ptr, ptr_align)?;
 
         if layout.size.bytes() == 0 {
-            return Ok(Some(Value::Scalar(Scalar::undef())));
+            return Ok(Some(Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { bits: 0, size: 0 }))));
         }
 
         let ptr = ptr.to_ptr()?;
@@ -1670,7 +1661,7 @@ fn unsize_into_ptr(
                     }
                     let (src_f_value, src_field) = match src {
                         Value::ByRef(ptr, align) => {
-                            let src_place = Place::from_scalar_ptr(ptr, align);
+                            let src_place = Place::from_scalar_ptr(ptr.into(), align);
                             let (src_f_place, src_field) =
                                 self.place_field(src_place, mir::Field::new(i), src_layout)?;
                             (self.read_place(src_f_place)?, src_field)
@@ -1717,7 +1708,7 @@ pub fn dump_local(&self, place: Place) {
                 }
                 write!(msg, ":").unwrap();
 
-                match self.stack[frame].get_local(local) {
+                match self.stack[frame].locals[local].access() {
                     Err(err) => {
                         if let EvalErrorKind::DeadLocal = err.kind {
                             write!(msg, " is dead").unwrap();
@@ -1736,16 +1727,16 @@ pub fn dump_local(&self, place: Place) {
                     }
                     Ok(Value::Scalar(val)) => {
                         write!(msg, " {:?}", val).unwrap();
-                        if let Scalar::Ptr(ptr) = val {
+                        if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val {
                             allocs.push(ptr.alloc_id);
                         }
                     }
                     Ok(Value::ScalarPair(val1, val2)) => {
                         write!(msg, " ({:?}, {:?})", val1, val2).unwrap();
-                        if let Scalar::Ptr(ptr) = val1 {
+                        if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val1 {
                             allocs.push(ptr.alloc_id);
                         }
-                        if let Scalar::Ptr(ptr) = val2 {
+                        if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val2 {
                             allocs.push(ptr.alloc_id);
                         }
                     }
@@ -1756,7 +1747,7 @@ pub fn dump_local(&self, place: Place) {
             }
             Place::Ptr { ptr, align, .. } => {
                 match ptr {
-                    Scalar::Ptr(ptr) => {
+                    ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => {
                         trace!("by align({}) ref:", align.abi());
                         self.memory.dump_alloc(ptr.alloc_id);
                     }
@@ -1766,21 +1757,6 @@ pub fn dump_local(&self, place: Place) {
         }
     }
 
-    /// Convenience function to ensure correct usage of locals
-    pub fn modify_local<F>(&mut self, frame: usize, local: mir::Local, f: F) -> EvalResult<'tcx>
-    where
-        F: FnOnce(&mut Self, Value) -> EvalResult<'tcx, Value>,
-    {
-        let val = self.stack[frame].get_local(local)?;
-        let new_val = f(self, val)?;
-        self.stack[frame].set_local(local, new_val)?;
-        // FIXME(solson): Run this when setting to Undef? (See previous version of this code.)
-        // if let Value::ByRef(ptr) = self.stack[frame].get_local(local) {
-        //     self.memory.deallocate(ptr)?;
-        // }
-        Ok(())
-    }
-
     pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo>, Span) {
         let mut last_span = None;
         let mut frames = Vec::new();
@@ -1819,12 +1795,12 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
         (frames, self.tcx.span)
     }
 
-    pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
-        super::sign_extend(self.tcx.tcx, value, ty)
+    pub fn sign_extend(&self, value: u128, ty: TyLayout<'_>) -> u128 {
+        super::sign_extend(value, ty)
     }
 
-    pub fn truncate(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
-        super::truncate(self.tcx.tcx, value, ty)
+    pub fn truncate(&self, value: u128, ty: TyLayout<'_>) -> u128 {
+        super::truncate(value, ty)
     }
 
     fn write_field_name(&self, s: &mut String, ty: Ty<'tcx>, i: usize, variant: usize) -> ::std::fmt::Result {
@@ -1893,34 +1869,45 @@ fn write_field_name(&self, s: &mut String, ty: Ty<'tcx>, i: usize, variant: usiz
             }
         }
     }
-}
 
-impl<'mir, 'tcx> Frame<'mir, 'tcx> {
-    pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> {
-        self.locals[local].ok_or_else(|| EvalErrorKind::DeadLocal.into())
+    pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue> {
+        trace!("{:?} is now live", local);
+
+        let ty = self.frame().mir.local_decls[local].ty;
+        let init = self.init_value(ty)?;
+        // StorageLive *always* kills the value that's currently stored
+        Ok(mem::replace(&mut self.frame_mut().locals[local], LocalValue::Live(init)))
     }
 
+    fn init_value(&mut self, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
+        let ty = self.monomorphize(ty, self.substs());
+        let layout = self.layout_of(ty)?;
+        Ok(match layout.abi {
+            layout::Abi::Scalar(..) => Value::Scalar(ScalarMaybeUndef::Undef),
+            layout::Abi::ScalarPair(..) => Value::ScalarPair(
+                ScalarMaybeUndef::Undef,
+                ScalarMaybeUndef::Undef,
+            ),
+            _ => Value::ByRef(self.alloc_ptr(layout)?.into(), layout.align),
+        })
+    }
+}
+
+impl<'mir, 'tcx> Frame<'mir, 'tcx> {
     fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> {
         match self.locals[local] {
-            None => err!(DeadLocal),
-            Some(ref mut local) => {
+            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Live(ref mut local) => {
                 *local = value;
                 Ok(())
             }
         }
     }
 
-    pub fn storage_live(&mut self, local: mir::Local) -> Option<Value> {
-        trace!("{:?} is now live", local);
-
-        // StorageLive *always* kills the value that's currently stored
-        mem::replace(&mut self.locals[local], Some(Value::Scalar(Scalar::undef())))
-    }
-
     /// Returns the old value of the local
-    pub fn storage_dead(&mut self, local: mir::Local) -> Option<Value> {
+    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue {
         trace!("{:?} is now dead", local);
 
-        self.locals[local].take()
+        mem::replace(&mut self.locals[local], LocalValue::Dead)
     }
 }
index 6e5cfe3bb3ee79f0c4b48bfd33fef1768d1b19a9..b62add8a559b41b3d9dc152f5327416e1190ae7e 100644 (file)
@@ -7,7 +7,7 @@
 use rustc::ty::ParamEnv;
 use rustc::ty::query::TyCtxtAt;
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
-use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value,
+use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value, ScalarMaybeUndef,
                             EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType};
 pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
@@ -272,10 +272,8 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
                 let alloc = self.get(ptr.alloc_id)?;
                 (ptr.offset.bytes(), alloc.align)
             }
-            Scalar::Bits { bits, defined } => {
-                if (defined as u64) < self.pointer_size().bits() {
-                    return err!(ReadUndefBytes);
-                }
+            Scalar::Bits { bits, size } => {
+                assert_eq!(size as u64, self.pointer_size().bytes());
                 // FIXME: what on earth does this line do? docs or fix needed!
                 let v = ((bits as u128) % (1 << self.pointer_size().bytes())) as u64;
                 if v == 0 {
@@ -756,7 +754,7 @@ pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<
         Ok(())
     }
 
-    pub fn read_scalar(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalResult<'tcx, Scalar> {
+    pub fn read_scalar(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalResult<'tcx, ScalarMaybeUndef> {
         self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer
         let endianness = self.endianness();
         let bytes = self.get_bytes_unchecked(ptr, size, ptr_align.min(self.int_align(size)))?;
@@ -764,7 +762,7 @@ pub fn read_scalar(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalRes
         // We must not return Ok() for unaligned pointers!
         if self.check_defined(ptr, size).is_err() {
             // this inflates undefined bytes to the entire scalar, even if only a few bytes are undefined
-            return Ok(Scalar::undef().into());
+            return Ok(ScalarMaybeUndef::Undef);
         }
         // Now we do the actual reading
         let bits = read_target_uint(endianness, bytes).unwrap();
@@ -776,44 +774,60 @@ pub fn read_scalar(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalRes
         } else {
             let alloc = self.get(ptr.alloc_id)?;
             match alloc.relocations.get(&ptr.offset) {
-                Some(&alloc_id) => return Ok(Pointer::new(alloc_id, Size::from_bytes(bits as u64)).into()),
+                Some(&alloc_id) => return Ok(ScalarMaybeUndef::Scalar(Pointer::new(alloc_id, Size::from_bytes(bits as u64)).into())),
                 None => {},
             }
         }
         // We don't. Just return the bits.
-        Ok(Scalar::Bits {
+        Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
             bits,
-            defined: size.bits() as u8,
-        })
+            size: size.bytes() as u8,
+        }))
     }
 
-    pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align) -> EvalResult<'tcx, Scalar> {
+    pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align) -> EvalResult<'tcx, ScalarMaybeUndef> {
         self.read_scalar(ptr, ptr_align, self.pointer_size())
     }
 
-    pub fn write_scalar(&mut self, ptr: Scalar, ptr_align: Align, val: Scalar, size: Size, signed: bool) -> EvalResult<'tcx> {
+    pub fn write_scalar(
+        &mut self,
+        ptr: Scalar,
+        ptr_align: Align,
+        val: ScalarMaybeUndef,
+        type_size: Size,
+        type_align: Align,
+        signed: bool,
+    ) -> EvalResult<'tcx> {
         let endianness = self.endianness();
+        self.check_align(ptr, ptr_align)?;
+
+        let val = match val {
+            ScalarMaybeUndef::Scalar(scalar) => scalar,
+            ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
+        };
 
         let bytes = match val {
             Scalar::Ptr(val) => {
-                assert_eq!(size, self.pointer_size());
+                assert_eq!(type_size, self.pointer_size());
                 val.offset.bytes() as u128
             }
 
-            Scalar::Bits { bits, defined } if defined as u64 >= size.bits() && size.bits() != 0 => bits,
-
-            Scalar::Bits { .. } => {
-                self.check_align(ptr.into(), ptr_align)?;
-                self.mark_definedness(ptr, size, false)?;
+            Scalar::Bits { size: 0, .. } => {
+                // nothing to do for ZSTs
+                assert_eq!(type_size.bytes(), 0);
                 return Ok(());
             }
+
+            Scalar::Bits { bits, size } => {
+                assert_eq!(size as u64, type_size.bytes());
+                bits
+            },
         };
 
         let ptr = ptr.to_ptr()?;
 
         {
-            let align = self.int_align(size);
-            let dst = self.get_bytes_mut(ptr, size, ptr_align.min(align))?;
+            let dst = self.get_bytes_mut(ptr, type_size, ptr_align.min(type_align))?;
             if signed {
                 write_target_int(endianness, dst, bytes as i128).unwrap();
             } else {
@@ -835,9 +849,9 @@ pub fn write_scalar(&mut self, ptr: Scalar, ptr_align: Align, val: Scalar, size:
         Ok(())
     }
 
-    pub fn write_ptr_sized_unsigned(&mut self, ptr: Pointer, ptr_align: Align, val: Scalar) -> EvalResult<'tcx> {
+    pub fn write_ptr_sized_unsigned(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef) -> EvalResult<'tcx> {
         let ptr_size = self.pointer_size();
-        self.write_scalar(ptr.into(), ptr_align, val, ptr_size, false)
+        self.write_scalar(ptr.into(), ptr_align, val, ptr_size, ptr_align, false)
     }
 
     fn int_align(&self, size: Size) -> Align {
@@ -984,7 +998,7 @@ pub trait HasMemory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
     fn into_ptr(
         &self,
         value: Value,
-    ) -> EvalResult<'tcx, Scalar> {
+    ) -> EvalResult<'tcx, ScalarMaybeUndef> {
         Ok(match value {
             Value::ByRef(ptr, align) => {
                 self.memory().read_ptr_sized(ptr.to_ptr()?, align)?
@@ -997,7 +1011,7 @@ fn into_ptr(
     fn into_ptr_vtable_pair(
         &self,
         value: Value,
-    ) -> EvalResult<'tcx, (Scalar, Pointer)> {
+    ) -> EvalResult<'tcx, (ScalarMaybeUndef, Pointer)> {
         match value {
             Value::ByRef(ref_ptr, align) => {
                 let mem = self.memory();
@@ -1005,11 +1019,11 @@ fn into_ptr_vtable_pair(
                 let vtable = mem.read_ptr_sized(
                     ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?,
                     align
-                )?.to_ptr()?;
+                )?.unwrap_or_err()?.to_ptr()?;
                 Ok((ptr, vtable))
             }
 
-            Value::ScalarPair(ptr, vtable) => Ok((ptr.into(), vtable.to_ptr()?)),
+            Value::ScalarPair(ptr, vtable) => Ok((ptr, vtable.unwrap_or_err()?.to_ptr()?)),
             _ => bug!("expected ptr and vtable, got {:?}", value),
         }
     }
@@ -1017,7 +1031,7 @@ fn into_ptr_vtable_pair(
     fn into_slice(
         &self,
         value: Value,
-    ) -> EvalResult<'tcx, (Scalar, u64)> {
+    ) -> EvalResult<'tcx, (ScalarMaybeUndef, u64)> {
         match value {
             Value::ByRef(ref_ptr, align) => {
                 let mem = self.memory();
@@ -1025,12 +1039,12 @@ fn into_slice(
                 let len = mem.read_ptr_sized(
                     ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?,
                     align
-                )?.to_bits(mem.pointer_size())? as u64;
+                )?.unwrap_or_err()?.to_bits(mem.pointer_size())? as u64;
                 Ok((ptr, len))
             }
             Value::ScalarPair(ptr, val) => {
-                let len = val.to_bits(self.memory().pointer_size())?;
-                Ok((ptr.into(), len as u64))
+                let len = val.unwrap_or_err()?.to_bits(self.memory().pointer_size())?;
+                Ok((ptr, len as u64))
             }
             Value::Scalar(_) => bug!("expected ptr and length, got {:?}", value),
         }
index 0c921f66198eb88d7538e9c0fdc1d56cb5700bd6..bc77f6e29d271dd61d7b21585f9c7b3ce75466da 100644 (file)
 mod terminator;
 mod traits;
 
-pub use self::eval_context::{EvalContext, Frame, StackPopCleanup,
-                             TyAndPacked, ValTy};
+pub use self::eval_context::{
+    EvalContext, Frame, StackPopCleanup,
+    TyAndPacked, ValTy,
+};
 
 pub use self::place::{Place, PlaceExtra};
 
 
 pub use self::memory::{write_target_uint, write_target_int, read_target_uint};
 
-use rustc::mir::interpret::{EvalResult, EvalErrorKind};
-use rustc::ty::{Ty, TyCtxt, ParamEnv};
+use rustc::ty::layout::TyLayout;
 
-pub fn sign_extend<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
-    let param_env = ParamEnv::empty();
-    let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?;
+pub fn sign_extend(value: u128, layout: TyLayout<'_>) -> u128 {
     let size = layout.size.bits();
     assert!(layout.abi.is_signed());
     // sign extend
     let shift = 128 - size;
     // shift the unsigned value to the left
     // and back to the right as signed (essentially fills with FF on the left)
-    Ok((((value << shift) as i128) >> shift) as u128)
+    (((value << shift) as i128) >> shift) as u128
 }
 
-pub fn truncate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
-    let param_env = ParamEnv::empty();
-    let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?;
+pub fn truncate(value: u128, layout: TyLayout<'_>) -> u128 {
     let size = layout.size.bits();
     let shift = 128 - size;
     // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
-    Ok((value << shift) >> shift)
+    (value << shift) >> shift
 }
index 8320add715769580611c146e197b535233f98e21..732c85bd0147a18ab56342c2bef097a5c10d8999 100644 (file)
@@ -1,7 +1,7 @@
 use rustc::mir;
 use rustc::ty::{self, Ty, layout};
 use syntax::ast::FloatTy;
-use rustc::ty::layout::LayoutOf;
+use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 
@@ -11,7 +11,7 @@
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
     fn binop_with_overflow(
-        &mut self,
+        &self,
         op: mir::BinOp,
         left: ValTy<'tcx>,
         right: ValTy<'tcx>,
@@ -32,7 +32,7 @@ pub fn intrinsic_with_overflow(
         dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx> {
         let (val, overflowed) = self.binop_with_overflow(op, left, right)?;
-        let val = Value::ScalarPair(val, Scalar::from_bool(overflowed));
+        let val = Value::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
         let valty = ValTy {
             value: val,
             ty: dest_ty,
@@ -97,13 +97,13 @@ pub fn binary_op(
             let signed = left_layout.abi.is_signed();
             let mut oflo = (r as u32 as u128) != r;
             let mut r = r as u32;
-            let size = left_layout.size.bits() as u32;
-            oflo |= r >= size;
+            let size = left_layout.size;
+            oflo |= r >= size.bits() as u32;
             if oflo {
-                r %= size;
+                r %= size.bits() as u32;
             }
             let result = if signed {
-                let l = self.sign_extend(l, left_ty)? as i128;
+                let l = self.sign_extend(l, left_layout) as i128;
                 let result = match bin_op {
                     Shl => l << r,
                     Shr => l >> r,
@@ -117,10 +117,10 @@ pub fn binary_op(
                     _ => bug!("it has already been checked that this is a shift op"),
                 }
             };
-            let truncated = self.truncate(result, left_ty)?;
+            let truncated = self.truncate(result, left_layout);
             return Ok((Scalar::Bits {
                 bits: truncated,
-                defined: size as u8,
+                size: size.bytes() as u8,
             }, oflo));
         }
 
@@ -145,8 +145,8 @@ pub fn binary_op(
                 _ => None,
             };
             if let Some(op) = op {
-                let l = self.sign_extend(l, left_ty)? as i128;
-                let r = self.sign_extend(r, right_ty)? as i128;
+                let l = self.sign_extend(l, left_layout) as i128;
+                let r = self.sign_extend(r, right_layout) as i128;
                 return Ok((Scalar::from_bool(op(&l, &r)), false));
             }
             let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
@@ -160,14 +160,14 @@ pub fn binary_op(
                 _ => None,
             };
             if let Some(op) = op {
-                let l128 = self.sign_extend(l, left_ty)? as i128;
-                let r = self.sign_extend(r, right_ty)? as i128;
-                let size = left_layout.size.bits();
+                let l128 = self.sign_extend(l, left_layout) as i128;
+                let r = self.sign_extend(r, right_layout) as i128;
+                let size = left_layout.size;
                 match bin_op {
                     Rem | Div => {
                         // int_min / -1
-                        if r == -1 && l == (1 << (size - 1)) {
-                            return Ok((Scalar::Bits { bits: l, defined: size as u8 }, true));
+                        if r == -1 && l == (1 << (size.bits() - 1)) {
+                            return Ok((Scalar::Bits { bits: l, size: size.bytes() as u8 }, true));
                         }
                     },
                     _ => {},
@@ -175,27 +175,27 @@ pub fn binary_op(
                 trace!("{}, {}, {}", l, l128, r);
                 let (result, mut oflo) = op(l128, r);
                 trace!("{}, {}", result, oflo);
-                if !oflo && size != 128 {
-                    let max = 1 << (size - 1);
+                if !oflo && size.bits() != 128 {
+                    let max = 1 << (size.bits() - 1);
                     oflo = result >= max || result < -max;
                 }
                 let result = result as u128;
-                let truncated = self.truncate(result, left_ty)?;
+                let truncated = self.truncate(result, left_layout);
                 return Ok((Scalar::Bits {
                     bits: truncated,
-                    defined: size as u8,
+                    size: size.bytes() as u8,
                 }, oflo));
             }
         }
 
         if let ty::TyFloat(fty) = left_ty.sty {
             macro_rules! float_math {
-                ($ty:path, $bitsize:expr) => {{
+                ($ty:path, $size:expr) => {{
                     let l = <$ty>::from_bits(l);
                     let r = <$ty>::from_bits(r);
                     let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>| Scalar::Bits {
                         bits: res.value.to_bits(),
-                        defined: $bitsize,
+                        size: $size,
                     };
                     let val = match bin_op {
                         Eq => Scalar::from_bool(l == r),
@@ -215,12 +215,12 @@ macro_rules! float_math {
                 }};
             }
             match fty {
-                FloatTy::F32 => float_math!(Single, 32),
-                FloatTy::F64 => float_math!(Double, 64),
+                FloatTy::F32 => float_math!(Single, 4),
+                FloatTy::F64 => float_math!(Double, 8),
             }
         }
 
-        let bit_width = self.layout_of(left_ty).unwrap().size.bits() as u8;
+        let size = self.layout_of(left_ty).unwrap().size.bytes() as u8;
 
         // only ints left
         let val = match bin_op {
@@ -232,9 +232,9 @@ macro_rules! float_math {
             Gt => Scalar::from_bool(l > r),
             Ge => Scalar::from_bool(l >= r),
 
-            BitOr => Scalar::Bits { bits: l | r, defined: bit_width },
-            BitAnd => Scalar::Bits { bits: l & r, defined: bit_width },
-            BitXor => Scalar::Bits { bits: l ^ r, defined: bit_width },
+            BitOr => Scalar::Bits { bits: l | r, size },
+            BitAnd => Scalar::Bits { bits: l & r, size },
+            BitXor => Scalar::Bits { bits: l ^ r, size },
 
             Add | Sub | Mul | Rem | Div => {
                 let op: fn(u128, u128) -> (u128, bool) = match bin_op {
@@ -248,10 +248,10 @@ macro_rules! float_math {
                     _ => bug!(),
                 };
                 let (result, oflo) = op(l, r);
-                let truncated = self.truncate(result, left_ty)?;
+                let truncated = self.truncate(result, left_layout);
                 return Ok((Scalar::Bits {
                     bits: truncated,
-                    defined: bit_width,
+                    size,
                 }, oflo || truncated != result));
             }
 
@@ -275,17 +275,16 @@ pub fn unary_op(
         &self,
         un_op: mir::UnOp,
         val: Scalar,
-        ty: Ty<'tcx>,
+        layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, Scalar> {
         use rustc::mir::UnOp::*;
         use rustc_apfloat::ieee::{Single, Double};
         use rustc_apfloat::Float;
 
-        let size = self.layout_of(ty)?.size;
+        let size = layout.size;
         let bytes = val.to_bits(size)?;
-        let size = size.bits();
 
-        let result_bytes = match (un_op, &ty.sty) {
+        let result_bytes = match (un_op, &layout.ty.sty) {
 
             (Not, ty::TyBool) => !val.to_bool()? as u128,
 
@@ -294,13 +293,13 @@ pub fn unary_op(
             (Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)),
             (Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)),
 
-            (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowNeg),
+            (Neg, _) if bytes == (1 << (size.bits() - 1)) => return err!(OverflowNeg),
             (Neg, _) => (-(bytes as i128)) as u128,
         };
 
         Ok(Scalar::Bits {
-            bits: self.truncate(result_bytes, ty)?,
-            defined: size as u8,
+            bits: self.truncate(result_bytes, layout),
+            size: size.bytes() as u8,
         })
     }
 }
index 59bf2ae6c0fe7721ea6c264715d87d94d4ad68f3..91c2519230695a08c8b621c53b387029312a417e 100644 (file)
@@ -3,7 +3,7 @@
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
 use rustc_data_structures::indexed_vec::Idx;
 
-use rustc::mir::interpret::{GlobalId, Value, Scalar, EvalResult, Pointer};
+use rustc::mir::interpret::{GlobalId, Value, Scalar, EvalResult, Pointer, ScalarMaybeUndef};
 use super::{EvalContext, Machine, ValTy};
 use interpret::memory::HasMemory;
 
@@ -14,7 +14,7 @@ pub enum Place {
         /// A place may have an invalid (integral or undef) pointer,
         /// since it might be turned back into a reference
         /// before ever being dereferenced.
-        ptr: Scalar,
+        ptr: ScalarMaybeUndef,
         align: Align,
         extra: PlaceExtra,
     },
@@ -35,10 +35,10 @@ pub enum PlaceExtra {
 impl<'tcx> Place {
     /// Produces a Place that will error if attempted to be read from
     pub fn undef() -> Self {
-        Self::from_scalar_ptr(Scalar::undef().into(), Align::from_bytes(1, 1).unwrap())
+        Self::from_scalar_ptr(ScalarMaybeUndef::Undef, Align::from_bytes(1, 1).unwrap())
     }
 
-    pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
+    pub fn from_scalar_ptr(ptr: ScalarMaybeUndef, align: Align) -> Self {
         Place::Ptr {
             ptr,
             align,
@@ -47,10 +47,10 @@ pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self {
     }
 
     pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
-        Self::from_scalar_ptr(ptr.into(), align)
+        Self::from_scalar_ptr(ScalarMaybeUndef::Scalar(ptr.into()), align)
     }
 
-    pub fn to_ptr_align_extra(self) -> (Scalar, Align, PlaceExtra) {
+    pub fn to_ptr_align_extra(self) -> (ScalarMaybeUndef, Align, PlaceExtra) {
         match self {
             Place::Ptr { ptr, align, extra } => (ptr, align, extra),
             _ => bug!("to_ptr_and_extra: expected Place::Ptr, got {:?}", self),
@@ -58,7 +58,7 @@ pub fn to_ptr_align_extra(self) -> (Scalar, Align, PlaceExtra) {
         }
     }
 
-    pub fn to_ptr_align(self) -> (Scalar, Align) {
+    pub fn to_ptr_align(self) -> (ScalarMaybeUndef, Align) {
         let (ptr, align, _extra) = self.to_ptr_align_extra();
         (ptr, align)
     }
@@ -66,7 +66,7 @@ pub fn to_ptr_align(self) -> (Scalar, Align) {
     pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
         // At this point, we forget about the alignment information -- the place has been turned into a reference,
         // and no matter where it came from, it now must be aligned.
-        self.to_ptr_align().0.to_ptr()
+        self.to_ptr_align().0.unwrap_or_err()?.to_ptr()
     }
 
     pub(super) fn elem_ty_and_len(
@@ -106,7 +106,7 @@ pub fn try_read_place(
             // Might allow this in the future, right now there's no way to do this from Rust code anyway
             Local(mir::RETURN_PLACE) => err!(ReadFromReturnPointer),
             // Directly reading a local will always succeed
-            Local(local) => self.frame().get_local(local).map(Some),
+            Local(local) => self.frame().locals[local].access().map(Some),
             // No fast path for statics. Reading from statics is rare and would require another
             // Machine function to handle differently in miri.
             Promoted(_) |
@@ -129,7 +129,7 @@ pub fn read_field(
         let field = base_layout.field(self, field_index)?;
         if field.size.bytes() == 0 {
             return Ok((
-                Value::Scalar(Scalar::undef()),
+                Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { bits: 0, size: 0 })),
                 field,
             ));
         }
@@ -197,9 +197,9 @@ pub fn read_place(&self, place: Place) -> EvalResult<'tcx, Value> {
         match place {
             Place::Ptr { ptr, align, extra } => {
                 assert_eq!(extra, PlaceExtra::None);
-                Ok(Value::ByRef(ptr, align))
+                Ok(Value::ByRef(ptr.unwrap_or_err()?, align))
             }
-            Place::Local { frame, local } => self.stack[frame].get_local(local),
+            Place::Local { frame, local } => self.stack[frame].locals[local].access(),
         }
     }
 
@@ -220,7 +220,7 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P
                 })?;
                 if let Value::ByRef(ptr, align) = val {
                     Place::Ptr {
-                        ptr,
+                        ptr: ptr.into(),
                         align,
                         extra: PlaceExtra::None,
                     }
@@ -238,7 +238,7 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P
                 };
                 let alloc = Machine::init_static(self, cid)?;
                 Place::Ptr {
-                    ptr: Scalar::Ptr(alloc.into()),
+                    ptr: ScalarMaybeUndef::Scalar(Scalar::Ptr(alloc.into())),
                     align: layout.align,
                     extra: PlaceExtra::None,
                 }
@@ -276,14 +276,13 @@ pub fn place_field(
         let (base_ptr, base_align, base_extra) = match base {
             Place::Ptr { ptr, align, extra } => (ptr, align, extra),
             Place::Local { frame, local } => {
-                match (&self.stack[frame].get_local(local)?, &base_layout.abi) {
+                match (self.stack[frame].locals[local].access()?, &base_layout.abi) {
                     // in case the field covers the entire type, just return the value
-                    (&Value::Scalar(_), &layout::Abi::Scalar(_)) |
-                    (&Value::ScalarPair(..), &layout::Abi::ScalarPair(..))
-                        if offset.bytes() == 0 && field.size == base_layout.size =>
-                    {
-                        return Ok((base, field));
-                    }
+                    (Value::Scalar(_), &layout::Abi::Scalar(_)) |
+                    (Value::ScalarPair(..), &layout::Abi::ScalarPair(..))
+                    if offset.bytes() == 0 && field.size == base_layout.size => {
+                        return Ok((base, field))
+                    },
                     _ => self.force_allocation(base)?.to_ptr_align_extra(),
                 }
             }
@@ -413,7 +412,7 @@ pub fn eval_place_projection(
             }
 
             Index(local) => {
-                let value = self.frame().get_local(local)?;
+                let value = self.frame().locals[local].access()?;
                 let ty = self.tcx.types.usize;
                 let n = self
                     .value_to_scalar(ValTy { value, ty })?
index db90714d0e6231d7b747fa142f8c6e21d112ac00..57b56db14bb4b719e00a19560a35120108d78211 100644 (file)
@@ -90,7 +90,7 @@ fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> {
 
             // Mark locals as alive
             StorageLive(local) => {
-                let old_val = self.frame_mut().storage_live(local);
+                let old_val = self.storage_live(local)?;
                 self.deallocate_local(old_val)?;
             }
 
index d750c1f47a662f5deb968d4289755e4d96f1f2d3..fe8071897c34874bd2b4ecc7178f6f3bd08af670 100644 (file)
@@ -2,7 +2,7 @@
 use rustc::ty::{self, Ty};
 use syntax::codemap::Span;
 
-use rustc::mir::interpret::{EvalResult, Scalar, Value};
+use rustc::mir::interpret::{EvalResult, Value};
 use interpret::{Machine, ValTy, EvalContext, Place, PlaceExtra};
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
@@ -33,7 +33,7 @@ pub(crate) fn drop_place(
                 ptr,
                 align: _,
                 extra: PlaceExtra::None,
-            } => ptr.to_value(),
+            } => Value::Scalar(ptr),
             _ => bug!("force_allocation broken"),
         };
         self.drop(val, instance, ty, span, target)
@@ -51,17 +51,10 @@ fn drop(
 
         let instance = match ty.sty {
             ty::TyDynamic(..) => {
-                let vtable = match arg {
-                    Value::ScalarPair(_, Scalar::Ptr(vtable)) => vtable,
-                    _ => bug!("expected fat ptr, got {:?}", arg),
-                };
-                match self.read_drop_type_from_vtable(vtable)? {
-                    Some(func) => func,
-                    // no drop fn -> bail out
-                    None => {
-                        self.goto_block(target);
-                        return Ok(())
-                    },
+                if let Value::ScalarPair(_, vtable) = arg {
+                    self.read_drop_type_from_vtable(vtable.unwrap_or_err()?.to_ptr()?)?
+                } else {
+                    bug!("expected fat ptr, got {:?}", arg);
                 }
             }
             _ => instance,
index 56dd3f603b692f63e615b109b117e540c88b2fe8..682e384da3936eb6caae8af7039e019d40805556 100644 (file)
@@ -4,7 +4,7 @@
 use syntax::codemap::Span;
 use rustc_target::spec::abi::Abi;
 
-use rustc::mir::interpret::{EvalResult, Scalar};
+use rustc::mir::interpret::{EvalResult, Scalar, Value};
 use super::{EvalContext, Place, Machine, ValTy};
 
 use rustc_data_structures::indexed_vec::Idx;
@@ -47,7 +47,7 @@ pub(super) fn eval_terminator(
 
                 for (index, &const_int) in values.iter().enumerate() {
                     // Compare using binary_op
-                    let const_int = Scalar::Bits { bits: const_int, defined: 128 };
+                    let const_int = Scalar::Bits { bits: const_int, size: discr_layout.size.bytes() as u8 };
                     let res = self.binary_op(mir::BinOp::Eq,
                         discr_prim, discr_val.ty,
                         const_int, discr_val.ty
@@ -392,12 +392,12 @@ fn eval_fn_call(
                 let fn_ptr = self.memory.read_ptr_sized(
                     vtable.offset(ptr_size * (idx as u64 + 3), &self)?,
                     ptr_align
-                )?.to_ptr()?;
+                )?.unwrap_or_err()?.to_ptr()?;
                 let instance = self.memory.get_fn(fn_ptr)?;
                 let mut args = args.to_vec();
                 let ty = self.layout_of(args[0].ty)?.field(&self, 0)?.ty;
                 args[0].ty = ty;
-                args[0].value = ptr.to_value();
+                args[0].value = Value::Scalar(ptr);
                 // recurse with concrete function
                 self.eval_fn_call(instance, destination, &args, span, sig)
             }
index b6c7feda19fa813377fff50213a3b046deb3b96c..84583680988b7c093c368eeb93cfd8d3c2aad59e 100644 (file)
@@ -1,6 +1,6 @@
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{Size, Align, LayoutOf};
-use rustc::mir::interpret::{Scalar, Value, Pointer, EvalResult};
+use rustc::mir::interpret::{Scalar, Pointer, EvalResult};
 
 use syntax::ast::Mutability;
 
@@ -36,25 +36,25 @@ pub fn get_vtable(
 
         let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
         let drop = self.memory.create_fn_alloc(drop);
-        self.memory.write_ptr_sized_unsigned(vtable, ptr_align, drop.into())?;
+        self.memory.write_ptr_sized_unsigned(vtable, ptr_align, Scalar::Ptr(drop).into())?;
 
         let size_ptr = vtable.offset(ptr_size, &self)?;
         self.memory.write_ptr_sized_unsigned(size_ptr, ptr_align, Scalar::Bits {
             bits: size as u128,
-            defined: ptr_size.bits() as u8,
-        })?;
+            size: ptr_size.bytes() as u8,
+        }.into())?;
         let align_ptr = vtable.offset(ptr_size * 2, &self)?;
         self.memory.write_ptr_sized_unsigned(align_ptr, ptr_align, Scalar::Bits {
             bits: align as u128,
-            defined: ptr_size.bits() as u8,
-        })?;
+            size: ptr_size.bytes() as u8,
+        }.into())?;
 
         for (i, method) in methods.iter().enumerate() {
             if let Some((def_id, substs)) = *method {
                 let instance = self.resolve(def_id, substs)?;
                 let fn_ptr = self.memory.create_fn_alloc(instance);
                 let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
-                self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, fn_ptr.into())?;
+                self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
             }
         }
 
@@ -69,16 +69,11 @@ pub fn get_vtable(
     pub fn read_drop_type_from_vtable(
         &self,
         vtable: Pointer,
-    ) -> EvalResult<'tcx, Option<ty::Instance<'tcx>>> {
+    ) -> EvalResult<'tcx, ty::Instance<'tcx>> {
         // we don't care about the pointee type, we just want a pointer
         let pointer_align = self.tcx.data_layout.pointer_align;
-        let pointer_size = self.tcx.data_layout.pointer_size.bits() as u8;
-        match self.read_ptr(vtable, pointer_align, self.tcx.mk_nil_ptr())? {
-            // some values don't need to call a drop impl, so the value is null
-            Value::Scalar(Scalar::Bits { bits: 0, defined} ) if defined == pointer_size => Ok(None),
-            Value::Scalar(Scalar::Ptr(drop_fn)) => self.memory.get_fn(drop_fn).map(Some),
-            _ => err!(ReadBytesAsPointer),
-        }
+        let drop_fn = self.memory.read_ptr_sized(vtable, pointer_align)?.unwrap_or_err()?.to_ptr()?;
+        self.memory.get_fn(drop_fn)
     }
 
     pub fn read_size_and_align_from_vtable(
@@ -87,11 +82,11 @@ pub fn read_size_and_align_from_vtable(
     ) -> EvalResult<'tcx, (Size, Align)> {
         let pointer_size = self.memory.pointer_size();
         let pointer_align = self.tcx.data_layout.pointer_align;
-        let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?, pointer_align)?.to_bits(pointer_size)? as u64;
+        let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?, pointer_align)?.unwrap_or_err()?.to_bits(pointer_size)? as u64;
         let align = self.memory.read_ptr_sized(
             vtable.offset(pointer_size * 2, self)?,
             pointer_align
-        )?.to_bits(pointer_size)? as u64;
+        )?.unwrap_or_err()?.to_bits(pointer_size)? as u64;
         Ok((Size::from_bytes(size), Align::from_bytes(align, align).unwrap()))
     }
 }
index 5f05783b15ccedca6a87c605a8e0facb095297f8..230d6f0472edde6f538b447f779b1adbdc057275 100644 (file)
 
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
-use rustc::mir::interpret::{AllocId, ConstValue};
+use rustc::mir::interpret::{AllocId, ConstValue, ScalarMaybeUndef};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
@@ -240,7 +240,7 @@ fn new() -> InliningMap<'tcx> {
         InliningMap {
             index: FxHashMap(),
             targets: Vec::new(),
-            inlines: BitVector::new(1024),
+            inlines: BitVector::with_capacity(1024),
         }
     }
 
@@ -770,7 +770,7 @@ fn is_available_upstream_generic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // If we are not in share generics mode, we don't link to upstream
         // monomorphizations but always instantiate our own internal versions
         // instead.
-        if !tcx.share_generics() {
+        if !tcx.sess.opts.share_generics() {
             return false
         }
 
@@ -1047,7 +1047,7 @@ fn push_if_root(&mut self, def_id: DefId) {
     /// the return type of `main`. This is not needed when
     /// the user writes their own `start` manually.
     fn push_extra_entry_roots(&mut self) {
-        if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryMain) {
+        if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryFnType::Main) {
             return
         }
 
@@ -1264,11 +1264,11 @@ fn collect_const<'a, 'tcx>(
     };
     match val {
         ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
-        ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
+        ConstValue::ScalarPair(Scalar::Ptr(a), ScalarMaybeUndef::Scalar(Scalar::Ptr(b))) => {
             collect_miri(tcx, a.alloc_id, output);
             collect_miri(tcx, b.alloc_id, output);
         }
-        ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
+        ConstValue::ScalarPair(_, ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr))) |
         ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
         ConstValue::Scalar(Scalar::Ptr(ptr)) =>
             collect_miri(tcx, ptr.alloc_id, output),
index bd0b2c6c278b131c526b0eb25605857e92e7c8c7..8d6d01633a12ef8d5faa6bb52f12bef0475ec9fa 100644 (file)
@@ -304,7 +304,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // available to downstream crates. This depends on whether we are in
     // share-generics mode and whether the current crate can even have
     // downstream crates.
-    let export_generics = tcx.share_generics() &&
+    let export_generics = tcx.sess.opts.share_generics() &&
                           tcx.local_crate_exports_generics();
 
     for mono_item in mono_items {
index 9902fe98cc011ecd2cb709478ed001ddceb70a0e..05e51c5430d7fe5aafd0f4b9741974e09722dc70 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::mir::interpret::{ConstEvalErr, EvalErrorKind};
+use rustc::mir::interpret::{ConstEvalErr, EvalErrorKind, ScalarMaybeUndef};
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
 use interpret::EvalContext;
@@ -368,8 +368,8 @@ fn const_prop(
                 type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some((
                     Value::Scalar(Scalar::Bits {
                         bits: n as u128,
-                        defined: self.tcx.data_layout.pointer_size.bits() as u8,
-                    }),
+                        size: self.tcx.data_layout.pointer_size.bytes() as u8,
+                    }.into()),
                     self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
                     span,
                 )))
@@ -390,8 +390,8 @@ fn const_prop(
                 let prim = self.use_ecx(source_info, |this| {
                     this.ecx.value_to_scalar(ValTy { value: val.0, ty: val.1.ty })
                 })?;
-                let val = self.use_ecx(source_info, |this| this.ecx.unary_op(op, prim, val.1.ty))?;
-                Some((Value::Scalar(val), place_layout, span))
+                let val = self.use_ecx(source_info, |this| this.ecx.unary_op(op, prim, val.1))?;
+                Some((Value::Scalar(val.into()), place_layout, span))
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
@@ -449,8 +449,8 @@ fn const_prop(
                 })?;
                 let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
                     Value::ScalarPair(
-                        val,
-                        Scalar::from_bool(overflow),
+                        val.into(),
+                        Scalar::from_bool(overflow).into(),
                     )
                 } else {
                     if overflow {
@@ -458,7 +458,7 @@ fn const_prop(
                         let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
                     }
-                    Value::Scalar(val)
+                    Value::Scalar(val.into())
                 };
                 Some((val, place_layout, span))
             },
@@ -576,7 +576,7 @@ fn visit_terminator_kind(
         if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
             if let Some(value) = self.eval_operand(cond, source_info) {
                 trace!("assertion on {:?} should be {:?}", value, expected);
-                if Value::Scalar(Scalar::from_bool(*expected)) != value.0 {
+                if Value::Scalar(Scalar::from_bool(*expected).into()) != value.0 {
                     // poison all places this operand references so that further code
                     // doesn't use the invalid value
                     match cond {
@@ -613,14 +613,18 @@ fn visit_terminator_kind(
                                 .eval_operand(len, source_info)
                                 .expect("len must be const");
                             let len = match len.0 {
-                                Value::Scalar(Scalar::Bits { bits, ..}) => bits,
+                                Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                                    bits, ..
+                                })) => bits,
                                 _ => bug!("const len not primitive: {:?}", len),
                             };
                             let index = self
                                 .eval_operand(index, source_info)
                                 .expect("index must be const");
                             let index = match index.0 {
-                                Value::Scalar(Scalar::Bits { bits, .. }) => bits,
+                                Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                                    bits, ..
+                                })) => bits,
                                 _ => bug!("const index not primitive: {:?}", index),
                             };
                             format!(
index 6a9258fe2c918eb5d4ae9b1574fdb8420c819ac0..a3647edd155d3d71b105891b4e16b16d7400a683 100644 (file)
@@ -433,7 +433,8 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
                 // This is correct for movable generators since borrows cannot live across
                 // suspension points. However for immovable generators we need to account for
-                // borrows, so we conseratively assume that all borrowed locals live forever.
+                // borrows, so we conseratively assume that all borrowed locals are live until
+                // we find a StorageDead statement referencing the locals.
                 // To do this we just union our `liveness` result with `borrowed_locals`, which
                 // contains all the locals which has been borrowed before this suspension point.
                 // If a borrow is converted to a raw reference, we must also assume that it lives
index 46fab544aafe98bf3430f3babc0e41ea463e0a29..85115427edae9dc00d0cfd7bf8e4f90f3ad79eb5 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::DefId;
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use rustc::mir::*;
@@ -271,7 +271,7 @@ fn should_inline(&self,
         // Traverse the MIR manually so we can account for the effects of
         // inlining on the CFG.
         let mut work_list = vec![START_BLOCK];
-        let mut visited = BitVector::new(callee_mir.basic_blocks().len());
+        let mut visited = BitArray::new(callee_mir.basic_blocks().len());
         while let Some(bb) = work_list.pop() {
             if !visited.insert(bb.index()) { continue; }
             let blk = &callee_mir.basic_blocks()[bb];
index 8a12a604ef2023156870e908ddcf9e3447019959..208679d2aa08adf3aa50a4c66c13b475c27ed8ea 100644 (file)
@@ -14,7 +14,7 @@
 //! The Qualif flags below can be used to also provide better
 //! diagnostics as to why a constant rvalue wasn't promoted.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::fx::FxHashSet;
@@ -116,7 +116,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     param_env: ty::ParamEnv<'tcx>,
     local_qualif: IndexVec<Local, Option<Qualif>>,
     qualif: Qualif,
-    const_fn_arg_vars: BitVector<Local>,
+    const_fn_arg_vars: BitArray<Local>,
     temp_promotion_state: IndexVec<Local, TempState>,
     promotion_candidates: Vec<Candidate>
 }
@@ -150,7 +150,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             param_env,
             local_qualif,
             qualif: Qualif::empty(),
-            const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
+            const_fn_arg_vars: BitArray::new(mir.local_decls.len()),
             temp_promotion_state: temps,
             promotion_candidates: vec![]
         }
@@ -284,7 +284,7 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
 
         let mir = self.mir;
 
-        let mut seen_blocks = BitVector::new(mir.basic_blocks().len());
+        let mut seen_blocks = BitArray::new(mir.basic_blocks().len());
         let mut bb = START_BLOCK;
         loop {
             seen_blocks.insert(bb.index());
index a7ef93eaec6b97c6fd814b996b692c3af7bdecc0..04a7a81eb126fc7f6e492ec6887e613fc678818c 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
 
@@ -45,7 +45,7 @@ fn is_nop_landing_pad(
         &self,
         bb: BasicBlock,
         mir: &Mir,
-        nop_landing_pads: &BitVector<BasicBlock>,
+        nop_landing_pads: &BitArray<BasicBlock>,
     ) -> bool {
         for stmt in &mir[bb].statements {
             match stmt.kind {
@@ -111,7 +111,7 @@ fn remove_nop_landing_pads(&self, mir: &mut Mir) {
 
         let mut jumps_folded = 0;
         let mut landing_pads_removed = 0;
-        let mut nop_landing_pads = BitVector::new(mir.basic_blocks().len());
+        let mut nop_landing_pads = BitArray::new(mir.basic_blocks().len());
 
         // This is a post-order traversal, so that if A post-dominates B
         // then A will be visited before B.
index 6b8d5a1489388403fa25a5f42d7f25cbc5d6590b..164790db4b5ec81b0f0ab62420b4481f8afc6419 100644 (file)
 //! naively generate still contains the `_a = ()` write in the unreachable block "after" the
 //! return.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
 use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext};
-use rustc::session::config::FullDebugInfo;
+use rustc::session::config::DebugInfo;
 use std::borrow::Cow;
 use transform::{MirPass, MirSource};
 
@@ -249,7 +249,7 @@ fn strip_nops(&mut self) {
 }
 
 pub fn remove_dead_blocks(mir: &mut Mir) {
-    let mut seen = BitVector::new(mir.basic_blocks().len());
+    let mut seen = BitArray::new(mir.basic_blocks().len());
     for (bb, _) in traversal::preorder(mir) {
         seen.insert(bb.index());
     }
@@ -285,7 +285,7 @@ fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource,
                           mir: &mut Mir<'tcx>) {
-        let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) };
+        let mut marker = DeclMarker { locals: BitArray::new(mir.local_decls.len()) };
         marker.visit_mir(mir);
         // Return pointer and arguments are always live
         marker.locals.insert(RETURN_PLACE);
@@ -294,7 +294,7 @@ fn run_pass<'a, 'tcx>(&self,
         }
 
         // We may need to keep dead user variables live for debuginfo.
-        if tcx.sess.opts.debuginfo == FullDebugInfo {
+        if tcx.sess.opts.debuginfo == DebugInfo::Full {
             for local in mir.vars_iter() {
                 marker.locals.insert(local);
             }
@@ -310,7 +310,7 @@ fn run_pass<'a, 'tcx>(&self,
 /// Construct the mapping while swapping out unused stuff out from the `vec`.
 fn make_local_map<'tcx, V>(
     vec: &mut IndexVec<Local, V>,
-    mask: BitVector<Local>,
+    mask: BitArray<Local>,
 ) -> IndexVec<Local, Option<Local>> {
     let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
     let mut used = Local::new(0);
@@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>(
 }
 
 struct DeclMarker {
-    pub locals: BitVector<Local>,
+    pub locals: BitArray<Local>,
 }
 
 impl<'tcx> Visitor<'tcx> for DeclMarker {
index 2d6b6cea030197b9673b715124d55f1e02f3a5ac..0a53361df6e95b70c53a1e1b69b7bfde5ed13d35 100644 (file)
@@ -203,8 +203,15 @@ fn cannot_uniquely_borrow_by_two_closures(
             desc,
             OGN = o
         );
-        err.span_label(old_loan_span, "first closure is constructed here");
-        err.span_label(new_loan_span, "second closure is constructed here");
+        if old_loan_span == new_loan_span {
+            err.span_label(
+                old_loan_span,
+                "closures are constructed here in different iterations of loop"
+            );
+        } else {
+            err.span_label(old_loan_span, "first closure is constructed here");
+            err.span_label(new_loan_span, "second closure is constructed here");
+        }
         if let Some(old_load_end_span) = old_load_end_span {
             err.span_label(old_load_end_span, "borrow from first closure ends here");
         }
index c6bad9e1980fb8b9627b3137da0409d57f376ff9..0ea90e745319004513a8df8a740f08a95d1a618a 100644 (file)
@@ -32,7 +32,7 @@ struct AstValidator<'a> {
 
 impl<'a> AstValidator<'a> {
     fn err_handler(&self) -> &errors::Handler {
-        &self.session.parse_sess.span_diagnostic
+        &self.session.diagnostic()
     }
 
     fn check_lifetime(&self, ident: Ident) {
index 405952065dacb6f9401254a327ace54e86cd2765..5c3a016a82b4c599955f62c1204333966b530bc3 100644 (file)
@@ -1015,7 +1015,7 @@ struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
 impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
     fn path_is_private_type(&self, path: &hir::Path) -> bool {
         let did = match path.def {
-            Def::PrimTy(..) | Def::SelfTy(..) => return false,
+            Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => return false,
             def => def.def_id(),
         };
 
index 4c8d42cf02f9832f216441a2ff1c192d845ba85c..837340f70fce757c35a998a321cfb77f1b19b97b 100644 (file)
@@ -17,3 +17,4 @@ arena = { path = "../libarena" }
 rustc_errors = { path = "../librustc_errors" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_metadata = { path = "../librustc_metadata" }
index da2847dc557930b5d8c12528f16101563112ce3b..c782f2072b9aaaacaed4b844c11f4f0691a6e033 100644 (file)
 use Namespace::{self, TypeNS, ValueNS, MacroNS};
 use {resolve_error, resolve_struct_error, ResolutionError};
 
-use rustc::middle::cstore::LoadedMacro;
 use rustc::hir::def::*;
 use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::ty;
+use rustc::middle::cstore::CrateStore;
+use rustc_metadata::cstore::LoadedMacro;
 
 use std::cell::Cell;
 use rustc_data_structures::sync::Lrc;
@@ -59,7 +60,20 @@ fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>
 impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) {
     fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
         arenas.alloc_name_binding(NameBinding {
-            kind: NameBindingKind::Def(self.0),
+            kind: NameBindingKind::Def(self.0, false),
+            vis: self.1,
+            span: self.2,
+            expansion: self.3,
+        })
+    }
+}
+
+pub(crate) struct IsMacroExport;
+
+impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport) {
+    fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
+        arenas.alloc_name_binding(NameBinding {
+            kind: NameBindingKind::Def(self.0, true),
             vis: self.1,
             span: self.2,
             expansion: self.3,
@@ -73,7 +87,7 @@ struct LegacyMacroImports {
     imports: Vec<(Name, Span)>,
 }
 
-impl<'a> Resolver<'a> {
+impl<'a, 'cl> Resolver<'a, 'cl> {
     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
     /// otherwise, reports an error.
     pub fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
@@ -616,7 +630,8 @@ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
     pub fn get_macro(&mut self, def: Def) -> Lrc<SyntaxExtension> {
         let def_id = match def {
             Def::Macro(def_id, ..) => def_id,
-            _ => panic!("Expected Def::Macro(..)"),
+            Def::NonMacroAttr => return Lrc::new(SyntaxExtension::NonMacroAttr),
+            _ => panic!("Expected Def::Macro(..) or Def::NonMacroAttr"),
         };
         if let Some(ext) = self.macro_map.get(&def_id) {
             return ext.clone();
@@ -762,16 +777,17 @@ fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImpor
     }
 }
 
-pub struct BuildReducedGraphVisitor<'a, 'b: 'a> {
-    pub resolver: &'a mut Resolver<'b>,
+pub struct BuildReducedGraphVisitor<'a, 'b: 'a, 'c: 'b> {
+    pub resolver: &'a mut Resolver<'b, 'c>,
     pub legacy_scope: LegacyScope<'b>,
     pub expansion: Mark,
 }
 
-impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
+impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> {
     fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
         let mark = id.placeholder_to_mark();
         self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
+        self.resolver.unresolved_invocations_macro_export.insert(mark);
         let invocation = self.resolver.invocations[&mark];
         invocation.module.set(self.resolver.current_module);
         invocation.legacy_scope.set(self.legacy_scope);
@@ -791,7 +807,7 @@ fn $visit(&mut self, node: &'a $ty) {
     }
 }
 
-impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
+impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
     method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
     method!(visit_expr:      ast::Expr,     ast::ExprKind::Mac,       walk_expr);
     method!(visit_pat:       ast::Pat,      ast::PatKind::Mac,        walk_pat);
index ec067a6477b6d84a7f12c5b738dd27f90fac2f4a..e1b059d2b733f30670ad6ae1eadd0982dcb5c83e 100644 (file)
@@ -31,8 +31,8 @@
 use syntax_pos::{Span, MultiSpan, DUMMY_SP};
 
 
-struct UnusedImportCheckVisitor<'a, 'b: 'a> {
-    resolver: &'a mut Resolver<'b>,
+struct UnusedImportCheckVisitor<'a, 'b: 'a, 'd: 'b> {
+    resolver: &'a mut Resolver<'b, 'd>,
     /// All the (so far) unused imports, grouped path list
     unused_imports: NodeMap<NodeMap<Span>>,
     base_id: ast::NodeId,
@@ -40,21 +40,21 @@ struct UnusedImportCheckVisitor<'a, 'b: 'a> {
 }
 
 // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
-impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> {
-    type Target = Resolver<'b>;
+impl<'a, 'b, 'd> Deref for UnusedImportCheckVisitor<'a, 'b, 'd> {
+    type Target = Resolver<'b, 'd>;
 
-    fn deref<'c>(&'c self) -> &'c Resolver<'b> {
+    fn deref<'c>(&'c self) -> &'c Resolver<'b, 'd> {
         &*self.resolver
     }
 }
 
-impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> {
-    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
+impl<'a, 'b, 'd> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'd> {
+    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'd> {
         &mut *self.resolver
     }
 }
 
-impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
+impl<'a, 'b, 'd> UnusedImportCheckVisitor<'a, 'b, 'd> {
     // We have information about whether `use` (import) directives are actually
     // used now. If an import is not used at all, we signal a lint error.
     fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) {
@@ -77,7 +77,7 @@ fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) {
     }
 }
 
-impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> {
+impl<'a, 'b, 'cl> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'cl> {
     fn visit_item(&mut self, item: &'a ast::Item) {
         self.item_span = item.span;
 
@@ -131,8 +131,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
                  directive.vis.get() == ty::Visibility::Public ||
                  directive.span.is_dummy() => {
                 if let ImportDirectiveSubclass::MacroUse = directive.subclass {
-                    if resolver.session.features_untracked().use_extern_macros &&
-                        !directive.span.is_dummy() {
+                    if resolver.use_extern_macros && !directive.span.is_dummy() {
                         resolver.session.buffer_lint(
                             lint::builtin::MACRO_USE_EXTERN_CRATE,
                             directive.id,
index 9714679949ff43013b7b9c41621c0856ceeaf578..a7fcc89f6b974209c651911f59c49c41a045d506 100644 (file)
@@ -26,6 +26,7 @@
 #[macro_use]
 extern crate rustc;
 extern crate rustc_data_structures;
+extern crate rustc_metadata;
 
 pub use rustc::hir::def::{Namespace, PerNS};
 
@@ -34,7 +35,7 @@
 
 use rustc::hir::map::{Definitions, DefCollector};
 use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
-use rustc::middle::cstore::{CrateStore, CrateLoader};
+use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::lint;
 use rustc::hir::def::*;
@@ -44,6 +45,9 @@
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 
+use rustc_metadata::creader::CrateLoader;
+use rustc_metadata::cstore::CStore;
+
 use syntax::codemap::CodeMap;
 use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
 mod build_reduced_graph;
 mod resolve_imports;
 
+fn is_known_tool(name: Name) -> bool {
+    ["clippy", "rustfmt"].contains(&&*name.as_str())
+}
+
 /// A free importable items suggested in case of resolution failure.
 struct ImportSuggestion {
     path: Path,
@@ -200,15 +208,10 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                         err.span_label(typaram_span, "type variable from outer function");
                     }
                 },
-                Def::Mod(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Variant(..) |
-                Def::Trait(..) | Def::TyAlias(..) | Def::TyForeign(..) | Def::TraitAlias(..) |
-                Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) |
-                Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) |
-                Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) |
-                Def::Existential(..) | Def::AssociatedExistential(..) |
-                Def::Macro(..) | Def::GlobalAsm(..) | Def::Err =>
+                _ => {
                     bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
                          Def::TyParam")
+                }
             }
 
             // Try to retrieve the span of the function signature and generate a new message with
@@ -688,7 +691,7 @@ fn visit_mod(
 }
 
 /// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes.
-impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
+impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> {
     fn visit_item(&mut self, item: &'tcx Item) {
         self.resolve_item(item);
     }
@@ -1118,7 +1121,7 @@ fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
 
 #[derive(Clone, Debug)]
 enum NameBindingKind<'a> {
-    Def(Def),
+    Def(Def, /* is_macro_export */ bool),
     Module(Module<'a>),
     Import {
         binding: &'a NameBinding<'a>,
@@ -1162,7 +1165,7 @@ fn module(&self) -> Option<Module<'a>> {
 
     fn def(&self) -> Def {
         match self.kind {
-            NameBindingKind::Def(def) => def,
+            NameBindingKind::Def(def, _) => def,
             NameBindingKind::Module(module) => module.def().unwrap(),
             NameBindingKind::Import { binding, .. } => binding.def(),
             NameBindingKind::Ambiguity { .. } => Def::Err,
@@ -1177,7 +1180,7 @@ fn def_ignoring_ambiguity(&self) -> Def {
         }
     }
 
-    fn get_macro(&self, resolver: &mut Resolver<'a>) -> Lrc<SyntaxExtension> {
+    fn get_macro<'b: 'a>(&self, resolver: &mut Resolver<'a, 'b>) -> Lrc<SyntaxExtension> {
         resolver.get_macro(self.def_ignoring_ambiguity())
     }
 
@@ -1192,8 +1195,8 @@ fn pseudo_vis(&self) -> ty::Visibility {
 
     fn is_variant(&self) -> bool {
         match self.kind {
-            NameBindingKind::Def(Def::Variant(..)) |
-            NameBindingKind::Def(Def::VariantCtor(..)) => true,
+            NameBindingKind::Def(Def::Variant(..), _) |
+            NameBindingKind::Def(Def::VariantCtor(..), _) => true,
             _ => false,
         }
     }
@@ -1242,7 +1245,7 @@ fn is_importable(&self) -> bool {
 
     fn is_macro_def(&self) -> bool {
         match self.kind {
-            NameBindingKind::Def(Def::Macro(..)) => true,
+            NameBindingKind::Def(Def::Macro(..), _) => true,
             _ => false,
         }
     }
@@ -1292,9 +1295,9 @@ fn intern(&mut self, string: &str, primitive_type: PrimTy) {
 /// The main resolver class.
 ///
 /// This is the visitor that walks the whole crate.
-pub struct Resolver<'a> {
+pub struct Resolver<'a, 'b: 'a> {
     session: &'a Session,
-    cstore: &'a dyn CrateStore,
+    cstore: &'a CStore,
 
     pub definitions: Definitions,
 
@@ -1390,7 +1393,7 @@ pub struct Resolver<'a> {
     /// true if `#![feature(use_extern_macros)]`
     use_extern_macros: bool,
 
-    crate_loader: &'a mut dyn CrateLoader,
+    crate_loader: &'a mut CrateLoader<'b>,
     macro_names: FxHashSet<Ident>,
     macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
     pub all_macros: FxHashMap<Name, Def>,
@@ -1398,7 +1401,7 @@ pub struct Resolver<'a> {
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
     macro_defs: FxHashMap<Mark, DefId>,
     local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
-    macro_exports: Vec<Export>,
+    macro_exports: Vec<Export>, // FIXME: Remove when `use_extern_macros` is stabilized
     pub whitelisted_legacy_custom_derives: Vec<Name>,
     pub found_unresolved_macro: bool,
 
@@ -1428,6 +1431,9 @@ pub struct Resolver<'a> {
 
     /// Only supposed to be used by rustdoc, otherwise should be false.
     pub ignore_extern_prelude_feature: bool,
+
+    /// Macro invocations in the whole crate that can expand into a `#[macro_export] macro_rules`.
+    unresolved_invocations_macro_export: FxHashSet<Mark>,
 }
 
 /// Nothing really interesting here, it just provides memory for the rest of the crate.
@@ -1471,7 +1477,7 @@ fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBindi
     }
 }
 
-impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> {
+impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> {
     fn parent(self, id: DefId) -> Option<DefId> {
         match id.krate {
             LOCAL_CRATE => self.definitions.def_key(id.index).parent,
@@ -1482,7 +1488,7 @@ fn parent(self, id: DefId) -> Option<DefId> {
 
 /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
 /// the resolver is no longer needed as all the relevant information is inline.
-impl<'a> hir::lowering::Resolver for Resolver<'a> {
+impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> {
     fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
         self.resolve_hir_path_cb(path, is_value,
                                  |resolver, span, error| resolve_error(resolver, span, error))
@@ -1535,7 +1541,7 @@ fn definitions(&mut self) -> &mut Definitions {
     }
 }
 
-impl<'a> Resolver<'a> {
+impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
     /// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a>
     /// isn't something that can be returned because it can't be made to live that long,
     /// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
@@ -1601,15 +1607,15 @@ fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error
     }
 }
 
-impl<'a> Resolver<'a> {
+impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
     pub fn new(session: &'a Session,
-               cstore: &'a dyn CrateStore,
+               cstore: &'a CStore,
                krate: &Crate,
                crate_name: &str,
                make_glob_map: MakeGlobMap,
-               crate_loader: &'a mut dyn CrateLoader,
+               crate_loader: &'a mut CrateLoader<'crateloader>,
                arenas: &'a ResolverArenas<'a>)
-               -> Resolver<'a> {
+               -> Resolver<'a, 'crateloader> {
         let root_def_id = DefId::local(CRATE_DEF_INDEX);
         let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
         let graph_root = arenas.alloc_module(ModuleData {
@@ -1702,15 +1708,13 @@ pub fn new(session: &'a Session,
 
             arenas,
             dummy_binding: arenas.alloc_name_binding(NameBinding {
-                kind: NameBindingKind::Def(Def::Err),
+                kind: NameBindingKind::Def(Def::Err, false),
                 expansion: Mark::root(),
                 span: DUMMY_SP,
                 vis: ty::Visibility::Public,
             }),
 
-            // The `proc_macro` and `decl_macro` features imply `use_extern_macros`
-            use_extern_macros:
-                features.use_extern_macros || features.decl_macro,
+            use_extern_macros: features.use_extern_macros(),
 
             crate_loader,
             macro_names: FxHashSet(),
@@ -1732,6 +1736,7 @@ pub fn new(session: &'a Session,
             current_type_ascription: Vec::new(),
             injected_crate: None,
             ignore_extern_prelude_feature: false,
+            unresolved_invocations_macro_export: FxHashSet(),
         }
     }
 
@@ -1842,6 +1847,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                       path_span: Span)
                                       -> Option<LexicalScopeBinding<'a>> {
         let record_used = record_used_id.is_some();
+        assert!(ns == TypeNS  || ns == ValueNS);
         if ns == TypeNS {
             ident.span = if ident.name == keywords::SelfType.name() {
                 // FIXME(jseyfried) improve `Self` hygiene
@@ -1918,8 +1924,9 @@ fn resolve_ident_in_lexical_scope(&mut self,
                     return Some(LexicalScopeBinding::Item(binding))
                 }
                 _ if poisoned.is_some() => break,
-                Err(Undetermined) => return None,
-                Err(Determined) => {}
+                Err(Determined) => continue,
+                Err(Undetermined) =>
+                    span_bug!(ident.span, "undetermined resolution during main resolution pass"),
             }
         }
 
@@ -1941,6 +1948,11 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                ident.span, Mark::root()).to_name_binding(self.arenas);
                 return Some(LexicalScopeBinding::Item(binding));
             }
+            if ns == TypeNS && is_known_tool(ident.name) {
+                let binding = (Def::ToolMod, ty::Visibility::Public,
+                               ident.span, Mark::root()).to_name_binding(self.arenas);
+                return Some(LexicalScopeBinding::Item(binding));
+            }
             if let Some(prelude) = self.prelude {
                 if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
                                                                         false, false, path_span) {
@@ -3501,6 +3513,8 @@ fn resolve_path(
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
                     if let Some(next_module) = binding.module() {
                         module = Some(next_module);
+                    } else if def == Def::ToolMod && i + 1 != path.len() {
+                        return PathResult::NonModule(PathResolution::new(Def::NonMacroAttr))
                     } else if def == Def::Err {
                         return PathResult::NonModule(err_path_resolution());
                     } else if opt_ns.is_some() && (is_last || maybe_assoc) {
index 29b6f958cc119c64719964bafcf04f50b569ec55..993874d7c0be883298fafce544016075b8088271 100644 (file)
@@ -8,16 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {AmbiguityError, CrateLint, Resolver, ResolutionError, resolve_error};
-use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult};
-use Namespace::{self, MacroNS};
-use build_reduced_graph::BuildReducedGraphVisitor;
+use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
+use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
+use Namespace::{self, TypeNS, MacroNS};
+use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
                          DefIndexAddressSpace};
 use rustc::hir::def::{Def, Export};
 use rustc::hir::map::{self, DefCollector};
 use rustc::{ty, lint};
+use rustc::middle::cstore::CrateStore;
 use syntax::ast::{self, Name, Ident};
 use syntax::attr::{self, HasAttrs};
 use syntax::errors::DiagnosticBuilder;
@@ -27,7 +28,7 @@
 use syntax::ext::hygiene::{self, Mark};
 use syntax::ext::placeholders::placeholder;
 use syntax::ext::tt::macro_rules;
-use syntax::feature_gate::{self, emit_feature_err, GateIssue};
+use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
 use syntax::fold::{self, Folder};
 use syntax::parse::parser::PathStyle;
 use syntax::parse::token::{self, Token};
@@ -117,7 +118,7 @@ pub fn def_ignoring_ambiguity(self) -> Def {
     }
 }
 
-impl<'a> base::Resolver for Resolver<'a> {
+impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
     fn next_node_id(&mut self) -> ast::NodeId {
         self.session.next_node_id()
     }
@@ -135,9 +136,11 @@ fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
     }
 
     fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
-        struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>, Span);
+        struct EliminateCrateVar<'b, 'a: 'b, 'crateloader: 'a>(
+            &'b mut Resolver<'a, 'crateloader>, Span
+        );
 
-        impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
+        impl<'a, 'b, 'crateloader> Folder for EliminateCrateVar<'a, 'b, 'crateloader> {
             fn fold_path(&mut self, path: ast::Path) -> ast::Path {
                 match self.fold_qpath(None, path) {
                     (None, path) => path,
@@ -193,7 +196,9 @@ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFra
 
         self.current_module = invocation.module.get();
         self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
+        self.unresolved_invocations_macro_export.remove(&mark);
         self.current_module.unresolved_invocations.borrow_mut().extend(derives);
+        self.unresolved_invocations_macro_export.extend(derives);
         for &derive in derives {
             self.invocations.insert(derive, invocation);
         }
@@ -215,7 +220,7 @@ fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
         let kind = ext.kind();
         self.macro_map.insert(def_id, ext);
         let binding = self.arenas.alloc_name_binding(NameBinding {
-            kind: NameBindingKind::Def(Def::Macro(def_id, kind)),
+            kind: NameBindingKind::Def(Def::Macro(def_id, kind), false),
             span: DUMMY_SP,
             vis: ty::Visibility::Invisible,
             expansion: Mark::root(),
@@ -324,6 +329,18 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
         if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
             self.report_proc_macro_stub(invoc.span());
             return Err(Determinacy::Determined);
+        } else if let Def::NonMacroAttr = def {
+            if let InvocationKind::Attr { .. } = invoc.kind {
+                if !self.session.features_untracked().tool_attributes {
+                    feature_err(&self.session.parse_sess, "tool_attributes",
+                                invoc.span(), GateIssue::Language,
+                                "tool attributes are unstable").emit();
+                }
+                return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr)));
+            } else {
+                self.report_non_macro_attr(invoc.path_span());
+                return Err(Determinacy::Determined);
+            }
         }
         let def_id = def.def_id();
 
@@ -346,6 +363,9 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, forc
             if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
                 self.report_proc_macro_stub(path.span);
                 return Err(Determinacy::Determined);
+            } else if let Def::NonMacroAttr = def {
+                self.report_non_macro_attr(path.span);
+                return Err(Determinacy::Determined);
             }
             self.unused_macros.remove(&def.def_id());
             Ok(self.get_macro(def))
@@ -370,12 +390,17 @@ fn check_unused_macros(&self) {
     }
 }
 
-impl<'a> Resolver<'a> {
+impl<'a, 'cl> Resolver<'a, 'cl> {
     fn report_proc_macro_stub(&self, span: Span) {
         self.session.span_err(span,
                               "can't use a procedural macro from the same crate that defines it");
     }
 
+    fn report_non_macro_attr(&self, span: Span) {
+        self.session.span_err(span,
+                              "expected a macro, found non-macro attribute");
+    }
+
     fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
                             -> Result<Def, Determinacy> {
         let (attr, traits, item) = match invoc.kind {
@@ -448,7 +473,15 @@ fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: b
 
     fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                             -> Result<Def, Determinacy> {
-        if kind != MacroKind::Bang && path.segments.len() > 1 {
+        let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
+        if def != Err(Determinacy::Undetermined) {
+            // Do not report duplicated errors on every undetermined resolution.
+            path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
+                self.session.span_err(segment.args.as_ref().unwrap().span(),
+                                      "generic arguments in macro path");
+            });
+        }
+        if kind != MacroKind::Bang && path.segments.len() > 1 && def != Ok(Def::NonMacroAttr) {
             if !self.session.features_untracked().proc_macro_path_invoc {
                 emit_feature_err(
                     &self.session.parse_sess,
@@ -460,15 +493,6 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
                 );
             }
         }
-
-        let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
-        if def != Err(Determinacy::Undetermined) {
-            // Do not report duplicated errors on every undetermined resolution.
-            path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
-                self.session.span_err(segment.args.as_ref().unwrap().span(),
-                                      "generic arguments in macro path");
-            });
-        }
         def
     }
 
@@ -542,67 +566,226 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
         result
     }
 
-    // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
+    // Resolve the initial segment of a non-global macro path
+    // (e.g. `foo` in `foo::bar!(); or `foo!();`).
+    // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
+    // expansion and import resolution (perhaps they can be merged in the future).
     pub fn resolve_lexical_macro_path_segment(&mut self,
                                               mut ident: Ident,
                                               ns: Namespace,
                                               record_used: bool,
                                               path_span: Span)
                                               -> Result<MacroBinding<'a>, Determinacy> {
+        // General principles:
+        // 1. Not controlled (user-defined) names should have higher priority than controlled names
+        //    built into the language or standard library. This way we can add new names into the
+        //    language or standard library without breaking user code.
+        // 2. "Closed set" below means new names can appear after the current resolution attempt.
+        // Places to search (in order of decreasing priority):
+        // (Type NS)
+        // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
+        //    (open set, not controlled).
+        // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
+        //    (open, not controlled).
+        // 3. Extern prelude (closed, not controlled).
+        // 4. Tool modules (closed, controlled right now, but not in the future).
+        // 5. Standard library prelude (de-facto closed, controlled).
+        // 6. Language prelude (closed, controlled).
+        // (Macro NS)
+        // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
+        //    (open, not controlled).
+        // 2. Macro prelude (language, standard library, user-defined legacy plugins lumped into
+        //    one set) (open, the open part is from macro expansions, not controlled).
+        // 2a. User-defined prelude from macro-use
+        //    (open, the open part is from macro expansions, not controlled).
+        // 2b. Standard library prelude, currently just a macro-use (closed, controlled)
+        // 2c. Language prelude, perhaps including builtin attributes
+        //    (closed, controlled, except for legacy plugins).
+        // 3. Builtin attributes (closed, controlled).
+
+        assert!(ns == TypeNS  || ns == MacroNS);
         ident = ident.modern();
-        let mut module = Some(self.current_module);
-        let mut potential_illegal_shadower = Err(Determinacy::Determined);
-        let determinacy =
-            if record_used { Determinacy::Determined } else { Determinacy::Undetermined };
+
+        // Names from inner scope that can't shadow names from outer scopes, e.g.
+        // mod m { ... }
+        // {
+        //     use prefix::*; // if this imports another `m`, then it can't shadow the outer `m`
+        //                    // and we have and ambiguity error
+        //     m::mac!();
+        // }
+        // This includes names from globs and from macro expansions.
+        let mut potentially_ambiguous_result: Option<MacroBinding> = None;
+
+        enum WhereToResolve<'a> {
+            Module(Module<'a>),
+            MacroPrelude,
+            BuiltinAttrs,
+            ExternPrelude,
+            ToolPrelude,
+            StdLibPrelude,
+            PrimitiveTypes,
+        }
+
+        // Go through all the scopes and try to resolve the name.
+        let mut where_to_resolve = WhereToResolve::Module(self.current_module);
+        let mut use_prelude = !self.current_module.no_implicit_prelude;
         loop {
-            let orig_current_module = self.current_module;
-            let result = if let Some(module) = module {
-                self.current_module = module; // Lexical resolutions can never be a privacy error.
-                // Since expanded macros may not shadow the lexical scope and
-                // globs may not shadow global macros (both enforced below),
-                // we resolve with restricted shadowing (indicated by the penultimate argument).
-                self.resolve_ident_in_module_unadjusted(
-                    module, ident, ns, true, record_used, path_span,
-                ).map(MacroBinding::Modern)
-            } else {
-                self.macro_prelude.get(&ident.name).cloned().ok_or(determinacy)
-                    .map(MacroBinding::Global)
+            let result = match where_to_resolve {
+                WhereToResolve::Module(module) => {
+                    let orig_current_module = mem::replace(&mut self.current_module, module);
+                    let binding = self.resolve_ident_in_module_unadjusted(
+                            module, ident, ns, true, record_used, path_span,
+                    );
+                    self.current_module = orig_current_module;
+                    binding.map(MacroBinding::Modern)
+                }
+                WhereToResolve::MacroPrelude => {
+                    match self.macro_prelude.get(&ident.name).cloned() {
+                        Some(binding) => Ok(MacroBinding::Global(binding)),
+                        None => Err(Determinacy::Determined),
+                    }
+                }
+                WhereToResolve::BuiltinAttrs => {
+                    if is_builtin_attr_name(ident.name) {
+                        let binding = (Def::NonMacroAttr, ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
+                WhereToResolve::ExternPrelude => {
+                    if use_prelude && self.extern_prelude.contains(&ident.name) {
+                        if !self.session.features_untracked().extern_prelude &&
+                           !self.ignore_extern_prelude_feature {
+                            feature_err(&self.session.parse_sess, "extern_prelude",
+                                        ident.span, GateIssue::Language,
+                                        "access to extern crates through prelude is experimental")
+                                        .emit();
+                        }
+
+                        let crate_id =
+                            self.crate_loader.process_path_extern(ident.name, ident.span);
+                        let crate_root =
+                            self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+                        self.populate_module_if_necessary(crate_root);
+
+                        let binding = (crate_root, ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
+                WhereToResolve::ToolPrelude => {
+                    if use_prelude && is_known_tool(ident.name) {
+                        let binding = (Def::ToolMod, ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
+                WhereToResolve::StdLibPrelude => {
+                    let mut result = Err(Determinacy::Determined);
+                    if use_prelude {
+                        if let Some(prelude) = self.prelude {
+                            if let Ok(binding) =
+                                    self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
+                                                                          false, false, path_span) {
+                                result = Ok(MacroBinding::Global(binding));
+                            }
+                        }
+                    }
+                    result
+                }
+                WhereToResolve::PrimitiveTypes => {
+                    if let Some(prim_ty) =
+                            self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
+                        let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
             };
-            self.current_module = orig_current_module;
 
-            match result.map(MacroBinding::binding) {
-                Ok(binding) => {
+            macro_rules! continue_search { () => {
+                where_to_resolve = match where_to_resolve {
+                    WhereToResolve::Module(module) => {
+                        match self.hygienic_lexical_parent(module, &mut ident.span) {
+                            Some(parent_module) => WhereToResolve::Module(parent_module),
+                            None => {
+                                use_prelude = !module.no_implicit_prelude;
+                                if ns == MacroNS {
+                                    WhereToResolve::MacroPrelude
+                                } else {
+                                    WhereToResolve::ExternPrelude
+                                }
+                            }
+                        }
+                    }
+                    WhereToResolve::MacroPrelude => WhereToResolve::BuiltinAttrs,
+                    WhereToResolve::BuiltinAttrs => break, // nowhere else to search
+                    WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
+                    WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
+                    WhereToResolve::StdLibPrelude => WhereToResolve::PrimitiveTypes,
+                    WhereToResolve::PrimitiveTypes => break, // nowhere else to search
+                };
+
+                continue;
+            }}
+
+            match result {
+                Ok(result) => {
                     if !record_used {
-                        return result;
+                        return Ok(result);
                     }
-                    if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower {
-                        if shadower.def() != binding.def() {
-                            let name = ident.name;
+
+                    let binding = result.binding();
+
+                    // Found a solution that is ambiguous with a previously found solution.
+                    // Push an ambiguity error for later reporting and
+                    // return something for better recovery.
+                    if let Some(previous_result) = potentially_ambiguous_result {
+                        if binding.def() != previous_result.binding().def() {
                             self.ambiguity_errors.push(AmbiguityError {
                                 span: path_span,
-                                name,
-                                b1: shadower,
+                                name: ident.name,
+                                b1: previous_result.binding(),
                                 b2: binding,
                                 lexical: true,
                             });
-                            return potential_illegal_shadower;
+                            return Ok(previous_result);
                         }
                     }
+
+                    // Found a solution that's not an ambiguity yet, but is "suspicious" and
+                    // can participate in ambiguities later on.
+                    // Remember it and go search for other solutions in outer scopes.
                     if binding.is_glob_import() || binding.expansion != Mark::root() {
-                        potential_illegal_shadower = result;
-                    } else {
-                        return result;
+                        potentially_ambiguous_result = Some(result);
+
+                        continue_search!();
                     }
+
+                    // Found a solution that can't be ambiguous, great success.
+                    return Ok(result);
                 },
+                Err(Determinacy::Determined) => {
+                    continue_search!();
+                }
                 Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
-                Err(Determinacy::Determined) => {}
             }
+        }
 
-            module = match module {
-                Some(module) => self.hygienic_lexical_parent(module, &mut ident.span),
-                None => return potential_illegal_shadower,
-            }
+        // Previously found potentially ambiguous result turned out to not be ambiguous after all.
+        if let Some(previous_result) = potentially_ambiguous_result {
+            return Ok(previous_result);
         }
+
+        if record_used { Err(Determinacy::Determined) } else { Err(Determinacy::Undetermined) }
     }
 
     pub fn resolve_legacy_scope(&mut self,
@@ -711,12 +894,15 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
 
             match (legacy_resolution, resolution) {
                 (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
-                    let msg1 = format!("`{}` could refer to the macro defined here", ident);
-                    let msg2 = format!("`{}` could also refer to the macro imported here", ident);
-                    self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
-                        .span_note(legacy_binding.span, &msg1)
-                        .span_note(binding.span, &msg2)
-                        .emit();
+                    if legacy_binding.def_id != binding.def_ignoring_ambiguity().def_id() {
+                        let msg1 = format!("`{}` could refer to the macro defined here", ident);
+                        let msg2 =
+                            format!("`{}` could also refer to the macro imported here", ident);
+                        self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
+                            .span_note(legacy_binding.span, &msg1)
+                            .span_note(binding.span, &msg2)
+                            .emit();
+                    }
                 },
                 (None, Err(_)) => {
                     assert!(def.is_none());
@@ -850,12 +1036,19 @@ pub fn define_macro(&mut self,
             let def = Def::Macro(def_id, MacroKind::Bang);
             self.all_macros.insert(ident.name, def);
             if attr::contains_name(&item.attrs, "macro_export") {
-                self.macro_exports.push(Export {
-                    ident: ident.modern(),
-                    def: def,
-                    vis: ty::Visibility::Public,
-                    span: item.span,
-                });
+                if self.use_extern_macros {
+                    let module = self.graph_root;
+                    let vis = ty::Visibility::Public;
+                    self.define(module, ident, MacroNS,
+                                (def, vis, item.span, expansion, IsMacroExport));
+                } else {
+                    self.macro_exports.push(Export {
+                        ident: ident.modern(),
+                        def: def,
+                        vis: ty::Visibility::Public,
+                        span: item.span,
+                    });
+                }
             } else {
                 self.unused_macros.insert(def_id);
             }
index acdb7c4d4edfc6feade1788dc50968215946d8d3..a3a9b938bbd6fd859b962bf12b2c942f321d1519 100644 (file)
@@ -123,7 +123,7 @@ fn binding(&self) -> Option<&'a NameBinding<'a>> {
     }
 }
 
-impl<'a> Resolver<'a> {
+impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
     fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
                   -> &'a RefCell<NameResolution<'a>> {
         *module.resolutions.borrow_mut().entry((ident.modern(), ns))
@@ -211,7 +211,9 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
         // if it cannot be shadowed by some new item/import expanded from a macro.
         // This happens either if there are no unexpanded macros, or expanded names cannot
         // shadow globs (that happens in macro namespace or with restricted shadowing).
-        let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty();
+        let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty() ||
+                                (ns == MacroNS && ptr::eq(module, self.graph_root) &&
+                                 !self.unresolved_invocations_macro_export.is_empty());
         if let Some(binding) = resolution.binding {
             if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
                 return check_usable(self, binding);
@@ -363,6 +365,18 @@ pub fn try_define(&mut self,
                         resolution.binding = Some(binding);
                         resolution.shadowed_glob = Some(old_binding);
                     }
+                } else if let (&NameBindingKind::Def(_, true), &NameBindingKind::Def(_, true)) =
+                        (&old_binding.kind, &binding.kind) {
+
+                    this.session.buffer_lint_with_diagnostic(
+                        DUPLICATE_MACRO_EXPORTS,
+                        CRATE_NODE_ID,
+                        binding.span,
+                        &format!("a macro named `{}` has already been exported", ident),
+                        BuiltinLintDiagnostics::DuplicatedMacroExports(
+                            ident, old_binding.span, binding.span));
+
+                    resolution.binding = Some(binding);
                 } else {
                     return Err(old_binding);
                 }
@@ -388,7 +402,7 @@ pub fn ambiguity(&self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
     // If the resolution becomes a success, define it in the module's glob importers.
     fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F)
                                -> T
-        where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
+        where F: FnOnce(&mut Resolver<'a, 'crateloader>, &mut NameResolution<'a>) -> T
     {
         // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
         // during which the resolution might end up getting re-defined via a glob cycle.
@@ -439,30 +453,30 @@ fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
     }
 }
 
-pub struct ImportResolver<'a, 'b: 'a> {
-    pub resolver: &'a mut Resolver<'b>,
+pub struct ImportResolver<'a, 'b: 'a, 'c: 'a + 'b> {
+    pub resolver: &'a mut Resolver<'b, 'c>,
 }
 
-impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> {
-    type Target = Resolver<'b>;
-    fn deref(&self) -> &Resolver<'b> {
+impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::Deref for ImportResolver<'a, 'b, 'c> {
+    type Target = Resolver<'b, 'c>;
+    fn deref(&self) -> &Resolver<'b, 'c> {
         self.resolver
     }
 }
 
-impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> {
-    fn deref_mut(&mut self) -> &mut Resolver<'b> {
+impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::DerefMut for ImportResolver<'a, 'b, 'c> {
+    fn deref_mut(&mut self) -> &mut Resolver<'b, 'c> {
         self.resolver
     }
 }
 
-impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> {
+impl<'a, 'b: 'a, 'c: 'a + 'b> ty::DefIdTree for &'a ImportResolver<'a, 'b, 'c> {
     fn parent(self, id: DefId) -> Option<DefId> {
         self.resolver.parent(id)
     }
 }
 
-impl<'a, 'b:'a> ImportResolver<'a, 'b> {
+impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
     // Import resolution
     //
     // This is a fixed-point algorithm. We resolve imports until our efforts
@@ -677,6 +691,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                             expansion: directive.expansion,
                         });
                         let _ = self.try_define(directive.parent, target, TypeNS, binding);
+                        let import = self.import_map.entry(directive.id).or_default();
+                        import[TypeNS] = Some(PathResolution::new(binding.def()));
                         return None;
                     }
                 }
@@ -766,7 +782,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                                     match binding.kind {
                                         // Never suggest the name that has binding error
                                         // i.e. the name that cannot be previously resolved
-                                        NameBindingKind::Def(Def::Err) => return None,
+                                        NameBindingKind::Def(Def::Err, _) => return None,
                                         _ => Some(&i.name),
                                     }
                                 },
index 761521c8807ca3f42147433202222d816b42590b..6e49951ff298ac652ffd9a841ca50b6e7b20ffde 100644 (file)
@@ -44,7 +44,7 @@
 use rustc::hir::map::{Node, NodeTraitItem, NodeImplItem};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::cstore::ExternCrate;
-use rustc::session::config::CrateType::CrateTypeExecutable;
+use rustc::session::config::CrateType;
 use rustc::ty::{self, TyCtxt};
 use rustc_typeck::hir_ty_to_ty;
 
@@ -811,6 +811,8 @@ fn fn_type(path: &ast::Path) -> bool {
             HirDef::Label(..) |
             HirDef::Macro(..) |
             HirDef::GlobalAsm(..) |
+            HirDef::ToolMod |
+            HirDef::NonMacroAttr |
             HirDef::Err => None,
         }
     }
@@ -1046,7 +1048,7 @@ fn output_file(&self, ctx: &SaveContext) -> File {
                 let executable = sess.crate_types
                     .borrow()
                     .iter()
-                    .any(|ct| *ct == CrateTypeExecutable);
+                    .any(|ct| *ct == CrateType::Executable);
                 let mut out_name = if executable {
                     "".to_owned()
                 } else {
index ca5aba5b6420a36bbfe1c1a18cbaf0248f3de947..f65fa341231e3893facf13ff9de9fe84b373a5d5 100644 (file)
@@ -23,6 +23,7 @@
 mod nvptx64;
 mod powerpc;
 mod powerpc64;
+mod riscv;
 mod s390x;
 mod sparc;
 mod sparc64;
@@ -500,6 +501,8 @@ pub fn adjust_for_cabi<C>(&mut self, cx: C, abi: ::spec::abi::Abi) -> Result<(),
             "nvptx" => nvptx::compute_abi_info(self),
             "nvptx64" => nvptx64::compute_abi_info(self),
             "hexagon" => hexagon::compute_abi_info(self),
+            "riscv32" => riscv::compute_abi_info(self, 32),
+            "riscv64" => riscv::compute_abi_info(self, 64),
             a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
         }
 
diff --git a/src/librustc_target/abi/call/riscv.rs b/src/librustc_target/abi/call/riscv.rs
new file mode 100644 (file)
index 0000000..fe0d748
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Reference: RISC-V ELF psABI specification
+// https://github.com/riscv/riscv-elf-psabi-doc
+
+use abi::call::{ArgType, FnType};
+
+fn classify_ret_ty<Ty>(arg: &mut ArgType<Ty>, xlen: u64) {
+    // "Scalars wider than 2✕XLEN are passed by reference and are replaced in
+    // the argument list with the address."
+    // "Aggregates larger than 2✕XLEN bits are passed by reference and are
+    // replaced in the argument list with the address, as are C++ aggregates
+    // with nontrivial copy constructors, destructors, or vtables."
+    if arg.layout.size.bits() > 2 * xlen {
+        arg.make_indirect();
+    }
+
+    // "When passed in registers, scalars narrower than XLEN bits are widened
+    // according to the sign of their type up to 32 bits, then sign-extended to
+    // XLEN bits."
+    arg.extend_integer_width_to(xlen); // this method only affects integer scalars
+}
+
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>, xlen: u64) {
+    // "Scalars wider than 2✕XLEN are passed by reference and are replaced in
+    // the argument list with the address."
+    // "Aggregates larger than 2✕XLEN bits are passed by reference and are
+    // replaced in the argument list with the address, as are C++ aggregates
+    // with nontrivial copy constructors, destructors, or vtables."
+    if arg.layout.size.bits() > 2 * xlen {
+        arg.make_indirect();
+    }
+
+    // "When passed in registers, scalars narrower than XLEN bits are widened
+    // according to the sign of their type up to 32 bits, then sign-extended to
+    // XLEN bits."
+    arg.extend_integer_width_to(xlen); // this method only affects integer scalars
+}
+
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>, xlen: u64) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(&mut fty.ret, xlen);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg_ty(arg, xlen);
+    }
+}
index 8f4911574398ba84d2f6874f334e371d8e93666f..a50a5a2d1cbe711014b1587563da7b3782177a81 100644 (file)
 //! is really just odds-and-ends relating to code gen and linking.
 //! This crate mostly exists to make rustc smaller, so we might put
 //! more 'stuff' here in the future.  It does not have a dependency on
-//! rustc_llvm.
-//!
-//! FIXME: Split this into two crates: one that has deps on syntax, and
-//! one that doesn't; the one that doesn't might get decent parallel
-//! build speedups.
+//! LLVM.
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
diff --git a/src/librustc_target/spec/aarch64_unknown_hermit.rs b/src/librustc_target/spec/aarch64_unknown_hermit.rs
new file mode 100644 (file)
index 0000000..6b81c62
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::hermit_base::opts();
+    base.max_atomic_width = Some(128);
+    base.abi_blacklist = super::arm_base::abi_blacklist();
+    base.linker = Some("aarch64-hermit-gcc".to_string());
+
+    Ok(Target {
+        llvm_target: "aarch64-unknown-hermit".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        target_os: "hermit".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs
new file mode 100644 (file)
index 0000000..2a24f77
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+    args.insert(LinkerFlavor::Gcc, vec![
+        "-Wl,-Bstatic".to_string(),
+        "-Wl,--no-dynamic-linker".to_string(),
+        "-Wl,--gc-sections".to_string(),
+        "-Wl,--as-needed".to_string(),
+    ]);
+
+    TargetOptions {
+        exe_allocation_crate: None,
+        executables: true,
+        has_elf_tls: true,
+        linker_is_gnu: true,
+        no_default_libraries: false,
+        panic_strategy: PanicStrategy::Abort,
+        position_independent_executables: false,
+        pre_link_args: args,
+        relocation_model: "static".to_string(),
+        target_family: Some("unix".to_string()),
+        tls_model: "local-exec".to_string(),
+        .. Default::default()
+    }
+}
index c5d21cdc46adb3fe589987b48a0cbe82ed358154..6faab77d7709f3cc7d320f12f742f928dde72e6c 100644 (file)
@@ -62,6 +62,7 @@
 mod dragonfly_base;
 mod freebsd_base;
 mod haiku_base;
+mod hermit_base;
 mod linux_base;
 mod linux_musl_base;
 mod openbsd_base;
@@ -373,6 +374,11 @@ fn $module() {
     ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf),
     ("i686-unknown-cloudabi", i686_unknown_cloudabi),
     ("x86_64-unknown-cloudabi", x86_64_unknown_cloudabi),
+
+    ("aarch64-unknown-hermit", aarch64_unknown_hermit),
+    ("x86_64-unknown-hermit", x86_64_unknown_hermit),
+
+    ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
new file mode 100644 (file)
index 0000000..cfd73e3
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use spec::abi::{Abi};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        llvm_target: "riscv32".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        arch: "riscv32".to_string(),
+        linker_flavor: LinkerFlavor::Ld,
+
+        options: TargetOptions {
+            linker: Some("riscv32-unknown-elf-ld".to_string()),
+            cpu: "generic-rv32".to_string(),
+            max_atomic_width: Some(32),
+            atomic_cas: false, // incomplete +a extension
+            features: "+m,+a".to_string(), // disable +c extension
+            executables: true,
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: "static".to_string(),
+            abi_blacklist: vec![
+                Abi::Cdecl,
+                Abi::Stdcall,
+                Abi::Fastcall,
+                Abi::Vectorcall,
+                Abi::Thiscall,
+                Abi::Aapcs,
+                Abi::Win64,
+                Abi::SysV64,
+                Abi::PtxKernel,
+                Abi::Msp430Interrupt,
+                Abi::X86Interrupt,
+            ],
+            .. Default::default()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/x86_64_unknown_hermit.rs b/src/librustc_target/spec/x86_64_unknown_hermit.rs
new file mode 100644 (file)
index 0000000..9f9f2e6
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::hermit_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+    base.linker = Some("x86_64-hermit-gcc".to_string());
+    base.max_atomic_width = Some(64);
+
+    Ok(Target {
+        llvm_target: "x86_64-unknown-hermit".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "hermit".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
index 4cde171f1bfd45f8356e43d56f0ffc0558cca29a..8c47df8b04221318e4ca7ddf1db159d303c57349 100644 (file)
@@ -1111,7 +1111,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
         if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() {
             if id == fn_id {
                 match entry_type {
-                    config::EntryMain => {
+                    config::EntryFnType::Main => {
                         let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
                         let trait_ref = ty::TraitRef::new(term_id, substs);
                         let return_ty_span = decl.output.span();
@@ -1122,7 +1122,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                             traits::Obligation::new(
                                 cause, param_env, trait_ref.to_predicate()));
                     },
-                    config::EntryStart => {},
+                    config::EntryFnType::Start => {},
                 }
             }
         }
index 0cc1f6333afa002859d3404f5511e1606e66bb8e..9fd5db16fb1089081bc6c552bd4a4ad8704b7f06 100644 (file)
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::query::Providers;
 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
+use rustc::util::profiling::ProfileCategory;
 use session::{CompileIncomplete, config};
 use util::common::time;
 
@@ -317,8 +318,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
         match entry_type {
-            config::EntryMain => check_main_fn_ty(tcx, id, sp),
-            config::EntryStart => check_start_fn_ty(tcx, id, sp),
+            config::EntryFnType::Main => check_main_fn_ty(tcx, id, sp),
+            config::EntryFnType::Start => check_start_fn_ty(tcx, id, sp),
         }
     }
 }
@@ -334,6 +335,8 @@ pub fn provide(providers: &mut Providers) {
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
                              -> Result<(), CompileIncomplete>
 {
+    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking));
+
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
     tcx.sess.track_errors(|| {
@@ -371,6 +374,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
 
+    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking));
+
     tcx.sess.compile_status()
 }
 
index c30d6817b466404d89e5c75c32f5558522dc4dd7..507aff0c3c727c5cab548ad824d9ca9c5a7ee6b7 100644 (file)
 // except according to those terms.
 
 use rustc::hir;
-use rustc::traits::{self, auto_trait as auto};
-use rustc::ty::{self, ToPredicate, TypeFoldable};
-use rustc::ty::subst::Subst;
-use rustc::infer::InferOk;
+use rustc::traits::auto_trait as auto;
+use rustc::ty::{self, TypeFoldable};
 use std::fmt::Debug;
-use syntax_pos::DUMMY_SP;
 
-use core::DocAccessLevels;
+use self::def_ctor::{get_def_from_def_id, get_def_from_node_id};
 
 use super::*;
 
-pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a> {
-    pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>,
+pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
+    pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>,
     pub f: auto::AutoTraitFinder<'a, 'tcx>,
 }
 
-impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
-    pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> Self {
+impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> {
+    pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
         let f = auto::AutoTraitFinder::new(&cx.tcx);
 
         AutoTraitFinder { cx, f }
     }
 
     pub fn get_with_def_id(&self, def_id: DefId) -> Vec<Item> {
-        let ty = self.cx.tcx.type_of(def_id);
-
-        let def_ctor: fn(DefId) -> Def = match ty.sty {
-            ty::TyAdt(adt, _) => match adt.adt_kind() {
-                AdtKind::Struct => Def::Struct,
-                AdtKind::Enum => Def::Enum,
-                AdtKind::Union => Def::Union,
-            }
-            ty::TyInt(_) |
-            ty::TyUint(_) |
-            ty::TyFloat(_) |
-            ty::TyStr |
-            ty::TyBool |
-            ty::TyChar => return self.get_auto_trait_impls(def_id, &move |_: DefId| {
-                match ty.sty {
-                    ty::TyInt(x) => Def::PrimTy(hir::TyInt(x)),
-                    ty::TyUint(x) => Def::PrimTy(hir::TyUint(x)),
-                    ty::TyFloat(x) => Def::PrimTy(hir::TyFloat(x)),
-                    ty::TyStr => Def::PrimTy(hir::TyStr),
-                    ty::TyBool => Def::PrimTy(hir::TyBool),
-                    ty::TyChar => Def::PrimTy(hir::TyChar),
-                    _ => unreachable!(),
-                }
-            }, None),
-            _ => {
-                debug!("Unexpected type {:?}", def_id);
-                return Vec::new()
-            }
-        };
-
-        self.get_auto_trait_impls(def_id, &def_ctor, None)
+        get_def_from_def_id(&self.cx, def_id, &|def_ctor| {
+            self.get_auto_trait_impls(def_id, &def_ctor, None)
+        })
     }
 
     pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec<Item> {
-        let item = &self.cx.tcx.hir.expect_item(id).node;
-        let did = self.cx.tcx.hir.local_def_id(id);
-
-        let def_ctor = match *item {
-            hir::ItemKind::Struct(_, _) => Def::Struct,
-            hir::ItemKind::Union(_, _) => Def::Union,
-            hir::ItemKind::Enum(_, _) => Def::Enum,
-            _ => panic!("Unexpected type {:?} {:?}", item, id),
-        };
-
-        self.get_auto_trait_impls(did, &def_ctor, Some(name))
-    }
-
-    fn get_real_ty<F>(&self,
-                      def_id: DefId,
-                      def_ctor: &F,
-                      real_name: &Option<Ident>,
-                      generics: &ty::Generics,
-    ) -> hir::Ty
-    where F: Fn(DefId) -> Def {
-        let path = get_path_for_type(self.cx.tcx, def_id, def_ctor);
-        let mut segments = path.segments.into_vec();
-        let last = segments.pop().unwrap();
-
-        segments.push(hir::PathSegment::new(
-            real_name.unwrap_or(last.ident),
-            self.generics_to_path_params(generics.clone()),
-            false,
-        ));
-
-        let new_path = hir::Path {
-            span: path.span,
-            def: path.def,
-            segments: HirVec::from_vec(segments),
-        };
-
-        hir::Ty {
-            id: ast::DUMMY_NODE_ID,
-            node: hir::TyKind::Path(hir::QPath::Resolved(None, P(new_path))),
-            span: DUMMY_SP,
-            hir_id: hir::DUMMY_HIR_ID,
-        }
-    }
-
-    pub fn get_blanket_impls<F>(
-        &self,
-        def_id: DefId,
-        def_ctor: &F,
-        name: Option<String>,
-        generics: &ty::Generics,
-    ) -> Vec<Item>
-    where F: Fn(DefId) -> Def {
-        let ty = self.cx.tcx.type_of(def_id);
-        let mut traits = Vec::new();
-        if self.cx.access_levels.borrow().is_doc_reachable(def_id) {
-            let real_name = name.clone().map(|name| Ident::from_str(&name));
-            let param_env = self.cx.tcx.param_env(def_id);
-            for &trait_def_id in self.cx.all_traits.iter() {
-                if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
-                   self.cx.generated_synthetics
-                          .borrow_mut()
-                          .get(&(def_id, trait_def_id))
-                          .is_some() {
-                    continue
-                }
-                self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
-                    self.cx.tcx.infer_ctxt().enter(|infcx| {
-                        let t_generics = infcx.tcx.generics_of(impl_def_id);
-                        let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id).unwrap();
-
-                        match infcx.tcx.type_of(impl_def_id).sty {
-                            ::rustc::ty::TypeVariants::TyParam(_) => {},
-                            _ => return,
-                        }
-
-                        let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
-                        let ty = ty.subst(infcx.tcx, substs);
-                        let param_env = param_env.subst(infcx.tcx, substs);
-
-                        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
-                        let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
-
-                        // Require the type the impl is implemented on to match
-                        // our type, and ignore the impl if there was a mismatch.
-                        let cause = traits::ObligationCause::dummy();
-                        let eq_result = infcx.at(&cause, param_env)
-                                             .eq(trait_ref.self_ty(), ty);
-                        if let Ok(InferOk { value: (), obligations }) = eq_result {
-                            // FIXME(eddyb) ignoring `obligations` might cause false positives.
-                            drop(obligations);
-
-                            let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
-                                cause.clone(),
-                                param_env,
-                                trait_ref.to_predicate(),
-                            ));
-                            if !may_apply {
-                                return
-                            }
-                            self.cx.generated_synthetics.borrow_mut()
-                                                        .insert((def_id, trait_def_id));
-                            let trait_ = hir::TraitRef {
-                                path: get_path_for_type(infcx.tcx,
-                                                        trait_def_id,
-                                                        hir::def::Def::Trait),
-                                ref_id: ast::DUMMY_NODE_ID,
-                            };
-                            let provided_trait_methods =
-                                infcx.tcx.provided_trait_methods(trait_def_id)
-                                         .into_iter()
-                                         .map(|meth| meth.ident.to_string())
-                                         .collect();
-
-                            let ty = self.get_real_ty(def_id, def_ctor, &real_name, generics);
-                            let predicates = infcx.tcx.predicates_of(impl_def_id);
-
-                            traits.push(Item {
-                                source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
-                                name: None,
-                                attrs: Default::default(),
-                                visibility: None,
-                                def_id: self.next_def_id(impl_def_id.krate),
-                                stability: None,
-                                deprecation: None,
-                                inner: ImplItem(Impl {
-                                    unsafety: hir::Unsafety::Normal,
-                                    generics: (t_generics, &predicates).clean(self.cx),
-                                    provided_trait_methods,
-                                    trait_: Some(trait_.clean(self.cx)),
-                                    for_: ty.clean(self.cx),
-                                    items: infcx.tcx.associated_items(impl_def_id)
-                                                    .collect::<Vec<_>>()
-                                                    .clean(self.cx),
-                                    polarity: None,
-                                    synthetic: false,
-                                    blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
-                                                                .clean(self.cx)),
-                                }),
-                            });
-                            debug!("{:?} => {}", trait_ref, may_apply);
-                        }
-                    });
-                });
-            }
-        }
-        traits
+        get_def_from_node_id(&self.cx, id, name, &|def_ctor, name| {
+            let did = self.cx.tcx.hir.local_def_id(id);
+            self.get_auto_trait_impls(did, &def_ctor, Some(name))
+        })
     }
 
     pub fn get_auto_trait_impls<F>(
@@ -262,7 +89,6 @@ pub fn get_auto_trait_impls<F>(
                 def_ctor,
                 tcx.require_lang_item(lang_items::SyncTraitLangItem),
             ).into_iter())
-            .chain(self.get_blanket_impls(def_id, def_ctor, name, &generics).into_iter())
             .collect();
 
         debug!(
@@ -338,14 +164,14 @@ fn get_auto_trait_impl_for<F>(
                 _ => unreachable!(),
             };
             let real_name = name.map(|name| Ident::from_str(&name));
-            let ty = self.get_real_ty(def_id, def_ctor, &real_name, &generics);
+            let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, &generics);
 
             return Some(Item {
                 source: Span::empty(),
                 name: None,
                 attrs: Default::default(),
                 visibility: None,
-                def_id: self.next_def_id(def_id.krate),
+                def_id: self.cx.next_def_id(def_id.krate),
                 stability: None,
                 deprecation: None,
                 inner: ImplItem(Impl {
@@ -364,56 +190,6 @@ fn get_auto_trait_impl_for<F>(
         None
     }
 
-    fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs {
-        let mut args = vec![];
-
-        for param in generics.params.iter() {
-            match param.kind {
-                ty::GenericParamDefKind::Lifetime => {
-                    let name = if param.name == "" {
-                        hir::ParamName::Plain(keywords::StaticLifetime.ident())
-                    } else {
-                        hir::ParamName::Plain(ast::Ident::from_interned_str(param.name))
-                    };
-
-                    args.push(hir::GenericArg::Lifetime(hir::Lifetime {
-                        id: ast::DUMMY_NODE_ID,
-                        span: DUMMY_SP,
-                        name: hir::LifetimeName::Param(name),
-                    }));
-                }
-                ty::GenericParamDefKind::Type {..} => {
-                    args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone())));
-                }
-            }
-        }
-
-        hir::GenericArgs {
-            args: HirVec::from_vec(args),
-            bindings: HirVec::new(),
-            parenthesized: false,
-        }
-    }
-
-    fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty {
-        debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id);
-        hir::Ty {
-            id: ast::DUMMY_NODE_ID,
-            node: hir::TyKind::Path(hir::QPath::Resolved(
-                None,
-                P(hir::Path {
-                    span: DUMMY_SP,
-                    def: Def::TyParam(param.def_id),
-                    segments: HirVec::from_vec(vec![
-                        hir::PathSegment::from_ident(Ident::from_interned_str(param.name))
-                    ]),
-                }),
-            )),
-            span: DUMMY_SP,
-            hir_id: hir::DUMMY_HIR_ID,
-        }
-    }
-
     fn find_auto_trait_generics(
         &self,
         did: DefId,
@@ -530,7 +306,7 @@ fn handle_lifetimes<'cx>(
                     // Desired order is 'larger, smaller', so flip then
                     if self.region_name(r1) != self.region_name(r2) {
                         finished
-                            .entry(self.region_name(r2).unwrap())
+                            .entry(self.region_name(r2).expect("no region_name found"))
                             .or_insert_with(|| Vec::new())
                             .push(r1);
                     }
@@ -565,7 +341,7 @@ fn handle_lifetimes<'cx>(
                         (&RegionTarget::Region(r1), &RegionTarget::Region(r2)) => {
                             if self.region_name(r1) != self.region_name(r2) {
                                 finished
-                                    .entry(self.region_name(r2).unwrap())
+                                    .entry(self.region_name(r2).expect("no region name found"))
                                     .or_insert_with(|| Vec::new())
                                     .push(r1) // Larger, smaller
                             }
@@ -662,7 +438,7 @@ fn make_final_bounds<'b, 'c, 'cx>(
             .flat_map(|(ty, mut bounds)| {
                 if let Some(data) = ty_to_fn.get(&ty) {
                     let (poly_trait, output) =
-                        (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned());
+                        (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned());
                     let new_ty = match &poly_trait.trait_ {
                         &Type::ResolvedPath {
                             ref path,
@@ -671,7 +447,8 @@ fn make_final_bounds<'b, 'c, 'cx>(
                             ref is_generic,
                         } => {
                             let mut new_path = path.clone();
-                            let last_segment = new_path.segments.pop().unwrap();
+                            let last_segment = new_path.segments.pop()
+                                                                .expect("segments were empty");
 
                             let (old_input, old_output) = match last_segment.args {
                                 GenericArgs::AngleBracketed { types, .. } => (types, None),
@@ -829,7 +606,7 @@ fn param_env_to_generics<'b, 'c, 'cx>(
                     let mut for_generics = self.extract_for_generics(tcx, orig_p.clone());
 
                     assert!(bounds.len() == 1);
-                    let mut b = bounds.pop().unwrap();
+                    let mut b = bounds.pop().expect("bounds were empty");
 
                     if b.is_sized_bound(self.cx) {
                         has_sized.insert(ty.clone());
@@ -859,7 +636,7 @@ fn param_env_to_generics<'b, 'c, 'cx>(
                             _ => false,
                         };
 
-                        let poly_trait = b.get_poly_trait().unwrap();
+                        let poly_trait = b.get_poly_trait().expect("Cannot get poly trait");
 
                         if is_fn {
                             ty_to_fn
@@ -912,7 +689,10 @@ fn param_env_to_generics<'b, 'c, 'cx>(
                                     // FIXME: Remove this scope when NLL lands
                                     {
                                         let args =
-                                            &mut new_trait_path.segments.last_mut().unwrap().args;
+                                            &mut new_trait_path.segments
+                                                .last_mut()
+                                                .expect("segments were empty")
+                                                .args;
 
                                         match args {
                                             // Convert somethiung like '<T as Iterator::Item> = u8'
@@ -1076,61 +856,6 @@ fn is_fn_ty(&self, tcx: &TyCtxt, ty: &Type) -> bool {
             _ => false,
         }
     }
-
-    // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly
-    // refactoring either librustdoc or librustc. In particular, allowing new DefIds to be
-    // registered after the AST is constructed would require storing the defid mapping in a
-    // RefCell, decreasing the performance for normal compilation for very little gain.
-    //
-    // Instead, we construct 'fake' def ids, which start immediately after the last DefId in
-    // DefIndexAddressSpace::Low. In the Debug impl for clean::Item, we explicitly check for fake
-    // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds
-    fn next_def_id(&self, crate_num: CrateNum) -> DefId {
-        let start_def_id = {
-            let next_id = if crate_num == LOCAL_CRATE {
-                self.cx
-                    .tcx
-                    .hir
-                    .definitions()
-                    .def_path_table()
-                    .next_id(DefIndexAddressSpace::Low)
-            } else {
-                self.cx
-                    .cstore
-                    .def_path_table(crate_num)
-                    .next_id(DefIndexAddressSpace::Low)
-            };
-
-            DefId {
-                krate: crate_num,
-                index: next_id,
-            }
-        };
-
-        let mut fake_ids = self.cx.fake_def_ids.borrow_mut();
-
-        let def_id = fake_ids.entry(crate_num).or_insert(start_def_id).clone();
-        fake_ids.insert(
-            crate_num,
-            DefId {
-                krate: crate_num,
-                index: DefIndex::from_array_index(
-                    def_id.index.as_array_index() + 1,
-                    def_id.index.address_space(),
-                ),
-            },
-        );
-
-        MAX_DEF_ID.with(|m| {
-            m.borrow_mut()
-                .entry(def_id.krate.clone())
-                .or_insert(start_def_id);
-        });
-
-        self.cx.all_fake_def_ids.borrow_mut().insert(def_id);
-
-        def_id.clone()
-    }
 }
 
 // Replaces all ReVars in a type with ty::Region's, using the provided map
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
new file mode 100644 (file)
index 0000000..5b352ff
--- /dev/null
@@ -0,0 +1,162 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir;
+use rustc::traits;
+use rustc::ty::ToPredicate;
+use rustc::ty::subst::Subst;
+use rustc::infer::InferOk;
+use syntax_pos::DUMMY_SP;
+
+use core::DocAccessLevels;
+
+use super::*;
+
+use self::def_ctor::{get_def_from_def_id, get_def_from_node_id};
+
+pub struct BlanketImplFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
+    pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>,
+}
+
+impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
+    pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
+        BlanketImplFinder { cx }
+    }
+
+    pub fn get_with_def_id(&self, def_id: DefId) -> Vec<Item> {
+        get_def_from_def_id(&self.cx, def_id, &|def_ctor| {
+            self.get_blanket_impls(def_id, &def_ctor, None)
+        })
+    }
+
+    pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec<Item> {
+        get_def_from_node_id(&self.cx, id, name, &|def_ctor, name| {
+            let did = self.cx.tcx.hir.local_def_id(id);
+            self.get_blanket_impls(did, &def_ctor, Some(name))
+        })
+    }
+
+    pub fn get_blanket_impls<F>(
+        &self,
+        def_id: DefId,
+        def_ctor: &F,
+        name: Option<String>,
+    ) -> Vec<Item>
+    where F: Fn(DefId) -> Def {
+        let mut impls = Vec::new();
+        if self.cx
+            .tcx
+            .get_attrs(def_id)
+            .lists("doc")
+            .has_word("hidden")
+        {
+            debug!(
+                "get_blanket_impls(def_id={:?}, def_ctor=...): item has doc('hidden'), \
+                 aborting",
+                def_id
+            );
+            return impls;
+        }
+        let ty = self.cx.tcx.type_of(def_id);
+        if self.cx.access_levels.borrow().is_doc_reachable(def_id) || ty.is_primitive() {
+            let generics = self.cx.tcx.generics_of(def_id);
+            let real_name = name.clone().map(|name| Ident::from_str(&name));
+            let param_env = self.cx.tcx.param_env(def_id);
+            for &trait_def_id in self.cx.all_traits.iter() {
+                if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
+                   self.cx.generated_synthetics
+                          .borrow_mut()
+                          .get(&(def_id, trait_def_id))
+                          .is_some() {
+                    continue
+                }
+                self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
+                    self.cx.tcx.infer_ctxt().enter(|infcx| {
+                        let t_generics = infcx.tcx.generics_of(impl_def_id);
+                        let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
+                                                 .expect("Cannot get impl trait");
+
+                        match trait_ref.self_ty().sty {
+                            ty::TypeVariants::TyParam(_) => {},
+                            _ => return,
+                        }
+
+                        let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
+                        let ty = ty.subst(infcx.tcx, substs);
+                        let param_env = param_env.subst(infcx.tcx, substs);
+
+                        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+                        let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
+
+                        // Require the type the impl is implemented on to match
+                        // our type, and ignore the impl if there was a mismatch.
+                        let cause = traits::ObligationCause::dummy();
+                        let eq_result = infcx.at(&cause, param_env)
+                                             .eq(trait_ref.self_ty(), ty);
+                        if let Ok(InferOk { value: (), obligations }) = eq_result {
+                            // FIXME(eddyb) ignoring `obligations` might cause false positives.
+                            drop(obligations);
+
+                            let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
+                                cause.clone(),
+                                param_env,
+                                trait_ref.to_predicate(),
+                            ));
+                            if !may_apply {
+                                return
+                            }
+                            self.cx.generated_synthetics.borrow_mut()
+                                                        .insert((def_id, trait_def_id));
+                            let trait_ = hir::TraitRef {
+                                path: get_path_for_type(infcx.tcx,
+                                                        trait_def_id,
+                                                        hir::def::Def::Trait),
+                                ref_id: ast::DUMMY_NODE_ID,
+                            };
+                            let provided_trait_methods =
+                                infcx.tcx.provided_trait_methods(trait_def_id)
+                                         .into_iter()
+                                         .map(|meth| meth.ident.to_string())
+                                         .collect();
+
+                            let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
+                            let predicates = infcx.tcx.predicates_of(impl_def_id);
+
+                            impls.push(Item {
+                                source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
+                                name: None,
+                                attrs: Default::default(),
+                                visibility: None,
+                                def_id: self.cx.next_def_id(impl_def_id.krate),
+                                stability: None,
+                                deprecation: None,
+                                inner: ImplItem(Impl {
+                                    unsafety: hir::Unsafety::Normal,
+                                    generics: (t_generics, &predicates).clean(self.cx),
+                                    provided_trait_methods,
+                                    trait_: Some(trait_.clean(self.cx)),
+                                    for_: ty.clean(self.cx),
+                                    items: infcx.tcx.associated_items(impl_def_id)
+                                                    .collect::<Vec<_>>()
+                                                    .clean(self.cx),
+                                    polarity: None,
+                                    synthetic: false,
+                                    blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
+                                                                .clean(self.cx)),
+                                }),
+                            });
+                        }
+                    });
+                });
+            }
+        }
+        impls
+    }
+}
diff --git a/src/librustdoc/clean/def_ctor.rs b/src/librustdoc/clean/def_ctor.rs
new file mode 100644 (file)
index 0000000..4db211b
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::DocContext;
+
+use super::*;
+
+pub fn get_def_from_def_id<F>(cx: &DocContext,
+                              def_id: DefId,
+                              callback: &F,
+) -> Vec<Item>
+where F: Fn(& dyn Fn(DefId) -> Def) -> Vec<Item> {
+    let ty = cx.tcx.type_of(def_id);
+
+    match ty.sty {
+        ty::TyAdt(adt, _) => callback(&match adt.adt_kind() {
+            AdtKind::Struct => Def::Struct,
+            AdtKind::Enum => Def::Enum,
+            AdtKind::Union => Def::Union,
+        }),
+        ty::TyInt(_) |
+        ty::TyUint(_) |
+        ty::TyFloat(_) |
+        ty::TyStr |
+        ty::TyBool |
+        ty::TyChar => callback(&move |_: DefId| {
+            match ty.sty {
+                ty::TyInt(x) => Def::PrimTy(hir::TyInt(x)),
+                ty::TyUint(x) => Def::PrimTy(hir::TyUint(x)),
+                ty::TyFloat(x) => Def::PrimTy(hir::TyFloat(x)),
+                ty::TyStr => Def::PrimTy(hir::TyStr),
+                ty::TyBool => Def::PrimTy(hir::TyBool),
+                ty::TyChar => Def::PrimTy(hir::TyChar),
+                _ => unreachable!(),
+            }
+        }),
+        _ => {
+            debug!("Unexpected type {:?}", def_id);
+            Vec::new()
+        }
+    }
+}
+
+pub fn get_def_from_node_id<F>(cx: &DocContext,
+                               id: ast::NodeId,
+                               name: String,
+                               callback: &F,
+) -> Vec<Item>
+where F: Fn(& dyn Fn(DefId) -> Def, String) -> Vec<Item> {
+    let item = &cx.tcx.hir.expect_item(id).node;
+
+    callback(&match *item {
+        hir::ItemKind::Struct(_, _) => Def::Struct,
+        hir::ItemKind::Union(_, _) => Def::Union,
+        hir::ItemKind::Enum(_, _) => Def::Enum,
+        _ => panic!("Unexpected type {:?} {:?}", item, id),
+    }, name)
+}
index 9245ef3cf507bd89cbcce6c3ff643de81bdbaf51..1c66c39b660b246cc5f32fab320488718139d8e5 100644 (file)
 use rustc::hir;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
-use rustc::middle::cstore::LoadedMacro;
+use rustc_metadata::cstore::LoadedMacro;
 use rustc::ty;
 use rustc::util::nodemap::FxHashSet;
 
 use core::{DocContext, DocAccessLevels};
 use doctree;
-use clean::{self, GetDefId, ToSource, get_auto_traits_with_def_id};
+use clean::{
+    self,
+    GetDefId,
+    ToSource,
+    get_auto_traits_with_def_id,
+    get_blanket_impls_with_def_id,
+};
 
 use super::Clean;
 
@@ -168,7 +174,7 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
         }
     });
     let fqn = if let clean::TypeKind::Macro = kind {
-        vec![crate_name, relative.last().unwrap()]
+        vec![crate_name, relative.last().expect("relative was empty")]
     } else {
         once(crate_name).chain(relative).collect()
     };
@@ -274,11 +280,14 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
 
     if auto_traits {
         let auto_impls = get_auto_traits_with_def_id(cx, did);
-        let mut renderinfo = cx.renderinfo.borrow_mut();
-        let new_impls: Vec<clean::Item> = auto_impls.into_iter()
-            .filter(|i| renderinfo.inlined.insert(i.def_id)).collect();
+        {
+            let mut renderinfo = cx.renderinfo.borrow_mut();
+            let new_impls: Vec<clean::Item> = auto_impls.into_iter()
+                .filter(|i| renderinfo.inlined.insert(i.def_id)).collect();
 
-        impls.extend(new_impls);
+            impls.extend(new_impls);
+        }
+        impls.extend(get_blanket_impls_with_def_id(cx, did));
     }
 
     // If this is the first time we've inlined something from another crate, then
@@ -336,10 +345,13 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
             build_impl(cx, def_id, &mut impls);
 
             let auto_impls = get_auto_traits_with_def_id(cx, def_id);
+            let blanket_impls = get_blanket_impls_with_def_id(cx, def_id);
             let mut renderinfo = cx.renderinfo.borrow_mut();
 
             let new_impls: Vec<clean::Item> = auto_impls.into_iter()
-                .filter(|i| renderinfo.inlined.insert(i.def_id)).collect();
+                .chain(blanket_impls.into_iter())
+                .filter(|i| renderinfo.inlined.insert(i.def_id))
+                .collect();
 
             impls.extend(new_impls);
         }
index 7454f79ed6bbb6f9b50905f332330c905dcbacbe..ad774f9860264b1f035c250779ae9afb3f1fdbbe 100644 (file)
 pub use self::Visibility::{Public, Inherited};
 
 use rustc_target::spec::abi::Abi;
-use syntax;
-use syntax::ast::{self, AttrStyle, Name, NodeId, Ident};
+use syntax::ast::{self, AttrStyle, Ident};
 use syntax::attr;
 use syntax::codemap::{dummy_spanned, Spanned};
-use syntax::feature_gate::UnstableFeatures;
 use syntax::ptr::P;
 use syntax::symbol::keywords::{self, Keyword};
-use syntax::symbol::{Symbol, InternedString};
+use syntax::symbol::InternedString;
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
 use rustc::mir::interpret::ConstValue;
 use rustc::mir::interpret::GlobalId;
 use rustc::hir::{self, GenericArg, HirVec};
 use rustc::hir::def::{self, Def, CtorKind};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::def_id::DefIndexAddressSpace;
-use rustc::hir::map::Node;
+use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
 use rustc::middle::stability;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_typeck::hir_ty_to_ty;
 use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
-use rustc::lint as lint;
 
 use std::collections::hash_map::Entry;
 use std::fmt;
 use std::cell::RefCell;
 use std::sync::Arc;
 use std::u32;
-use std::ops::Range;
 
 use core::{self, DocContext};
 use doctree;
 use visit_ast;
 use html::render::{cache, ExternalLocation};
 use html::item_type::ItemType;
-use html::markdown::markdown_links;
 
 pub mod inline;
 pub mod cfg;
 mod simplify;
 mod auto_trait;
+mod blanket_impl;
+pub mod def_ctor;
 
 use self::cfg::Cfg;
 use self::auto_trait::AutoTraitFinder;
+use self::blanket_impl::BlanketImplFinder;
 
-thread_local!(static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = RefCell::new(FxHashMap()));
+thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> =
+    RefCell::new(FxHashMap()));
 
 const FN_OUTPUT_NAME: &'static str = "Output";
 
@@ -145,7 +142,7 @@ pub struct Crate {
     pub masked_crates: FxHashSet<CrateNum>,
 }
 
-impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx> {
+impl<'a, 'tcx, 'rcx, 'cstore> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
     fn clean(&self, cx: &DocContext) -> Crate {
         use ::visit_lib::LibEmbargoVisitor;
 
@@ -569,7 +566,7 @@ pub struct Module {
 impl Clean<Item> for doctree::Module {
     fn clean(&self, cx: &DocContext) -> Item {
         let name = if self.name.is_some() {
-            self.name.unwrap().clean(cx)
+            self.name.expect("No name provided").clean(cx)
         } else {
             "".to_string()
         };
@@ -577,32 +574,7 @@ fn clean(&self, cx: &DocContext) -> Item {
         // maintain a stack of mod ids, for doc comment path resolution
         // but we also need to resolve the module's own docs based on whether its docs were written
         // inside or outside the module, so check for that
-        let attrs = if self.attrs.iter()
-                                 .filter(|a| a.check_name("doc"))
-                                 .next()
-                                 .map_or(true, |a| a.style == AttrStyle::Inner) {
-            // inner doc comment, use the module's own scope for resolution
-            if self.id != NodeId::new(0) {
-                *cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(self.id));
-            } else {
-                *cx.current_item_name.borrow_mut() = None;
-            }
-            cx.mod_ids.borrow_mut().push(self.id);
-            self.attrs.clean(cx)
-        } else {
-            // outer doc comment, use its parent's scope
-            match cx.mod_ids.borrow().last() {
-                Some(parent) if *parent != NodeId::new(0) => {
-                    *cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(*parent));
-                }
-                _ => {
-                    *cx.current_item_name.borrow_mut() = None;
-                }
-            }
-            let attrs = self.attrs.clean(cx);
-            cx.mod_ids.borrow_mut().push(self.id);
-            attrs
-        };
+        let attrs = self.attrs.clean(cx);
 
         let mut items: Vec<Item> = vec![];
         items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
@@ -621,8 +593,6 @@ fn clean(&self, cx: &DocContext) -> Item {
         items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.macros.iter().map(|x| x.clean(cx)));
 
-        cx.mod_ids.borrow_mut().pop();
-
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
         let whence = {
@@ -782,6 +752,7 @@ pub struct Attributes {
     pub span: Option<syntax_pos::Span>,
     /// map from Rust paths to resolved defs and potential URL fragments
     pub links: Vec<(String, Option<DefId>, Option<String>)>,
+    pub inner_docs: bool,
 }
 
 impl Attributes {
@@ -926,12 +897,18 @@ pub fn from_ast(diagnostic: &::errors::Handler,
             }
         }
 
+        let inner_docs = attrs.iter()
+                              .filter(|a| a.check_name("doc"))
+                              .next()
+                              .map_or(true, |a| a.style == AttrStyle::Inner);
+
         Attributes {
             doc_strings,
             other_attrs,
             cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
             span: sp,
             links: vec![],
+            inner_docs,
         }
     }
 
@@ -1024,483 +1001,9 @@ fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
     }
 }
 
-/// Given a def, returns its name and disambiguator
-/// for a value namespace
-///
-/// Returns None for things which cannot be ambiguous since
-/// they exist in both namespaces (structs and modules)
-fn value_ns_kind(def: Def, path_str: &str) -> Option<(&'static str, String)> {
-    match def {
-        // structs, variants, and mods exist in both namespaces. skip them
-        Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) | Def::VariantCtor(..) => None,
-        Def::Fn(..)
-            => Some(("function", format!("{}()", path_str))),
-        Def::Method(..)
-            => Some(("method", format!("{}()", path_str))),
-        Def::Const(..)
-            => Some(("const", format!("const@{}", path_str))),
-        Def::Static(..)
-            => Some(("static", format!("static@{}", path_str))),
-        _ => Some(("value", format!("value@{}", path_str))),
-    }
-}
-
-/// Given a def, returns its name, the article to be used, and a disambiguator
-/// for the type namespace
-fn type_ns_kind(def: Def, path_str: &str) -> (&'static str, &'static str, String) {
-    let (kind, article) = match def {
-        // we can still have non-tuple structs
-        Def::Struct(..) => ("struct", "a"),
-        Def::Enum(..) => ("enum", "an"),
-        Def::Trait(..) => ("trait", "a"),
-        Def::Union(..) => ("union", "a"),
-        _ => ("type", "a"),
-    };
-    (kind, article, format!("{}@{}", kind, path_str))
-}
-
-fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
-    if attrs.doc_strings.is_empty() {
-        return DUMMY_SP;
-    }
-    let start = attrs.doc_strings[0].span();
-    let end = attrs.doc_strings.last().unwrap().span();
-    start.to(end)
-}
-
-fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
-                   path_str: &str,
-                   article1: &str, kind1: &str, disambig1: &str,
-                   article2: &str, kind2: &str, disambig2: &str) {
-    let sp = span_of_attrs(attrs);
-    cx.sess()
-      .struct_span_warn(sp,
-                        &format!("`{}` is both {} {} and {} {}",
-                                 path_str, article1, kind1,
-                                 article2, kind2))
-      .help(&format!("try `{}` if you want to select the {}, \
-                      or `{}` if you want to \
-                      select the {}",
-                      disambig1, kind1, disambig2,
-                      kind2))
-      .emit();
-}
-
-/// Given an enum variant's def, return the def of its enum and the associated fragment
-fn handle_variant(cx: &DocContext, def: Def) -> Result<(Def, Option<String>), ()> {
-    use rustc::ty::DefIdTree;
-
-    let parent = if let Some(parent) = cx.tcx.parent(def.def_id()) {
-        parent
-    } else {
-        return Err(())
-    };
-    let parent_def = Def::Enum(parent);
-    let variant = cx.tcx.expect_variant_def(def);
-    Ok((parent_def, Some(format!("{}.v", variant.name))))
-}
-
-const PRIMITIVES: &[(&str, Def)] = &[
-    ("u8",    Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U8))),
-    ("u16",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U16))),
-    ("u32",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U32))),
-    ("u64",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U64))),
-    ("u128",  Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U128))),
-    ("usize", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::Usize))),
-    ("i8",    Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I8))),
-    ("i16",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I16))),
-    ("i32",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I32))),
-    ("i64",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I64))),
-    ("i128",  Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I128))),
-    ("isize", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::Isize))),
-    ("f32",   Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F32))),
-    ("f64",   Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F64))),
-    ("str",   Def::PrimTy(hir::PrimTy::TyStr)),
-    ("bool",  Def::PrimTy(hir::PrimTy::TyBool)),
-    ("char",  Def::PrimTy(hir::PrimTy::TyChar)),
-];
-
-fn is_primitive(path_str: &str, is_val: bool) -> Option<Def> {
-    if is_val {
-        None
-    } else {
-        PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1)
-    }
-}
-
-/// Resolve a given string as a path, along with whether or not it is
-/// in the value namespace. Also returns an optional URL fragment in the case
-/// of variants and methods
-fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option<String>), ()> {
-    // In case we're in a module, try to resolve the relative
-    // path
-    if let Some(id) = cx.mod_ids.borrow().last() {
-        let result = cx.resolver.borrow_mut()
-                                .with_scope(*id,
-            |resolver| {
-                resolver.resolve_str_path_error(DUMMY_SP,
-                                                &path_str, is_val)
-        });
-
-        if let Ok(result) = result {
-            // In case this is a trait item, skip the
-            // early return and try looking for the trait
-            let value = match result.def {
-                Def::Method(_) | Def::AssociatedConst(_) => true,
-                Def::AssociatedTy(_) => false,
-                Def::Variant(_) => return handle_variant(cx, result.def),
-                // not a trait item, just return what we found
-                _ => return Ok((result.def, None))
-            };
-
-            if value != is_val {
-                return Err(())
-            }
-        } else if let Some(prim) = is_primitive(path_str, is_val) {
-            return Ok((prim, Some(path_str.to_owned())))
-        } else {
-            // If resolution failed, it may still be a method
-            // because methods are not handled by the resolver
-            // If so, bail when we're not looking for a value
-            if !is_val {
-                return Err(())
-            }
-        }
-
-        // Try looking for methods and associated items
-        let mut split = path_str.rsplitn(2, "::");
-        let item_name = if let Some(first) = split.next() {
-            first
-        } else {
-            return Err(())
-        };
-
-        let mut path = if let Some(second) = split.next() {
-            second.to_owned()
-        } else {
-            return Err(())
-        };
-
-        if path == "self" || path == "Self" {
-            if let Some(name) = *cx.current_item_name.borrow() {
-                path = name.to_string();
-            }
-        }
-
-        let ty = cx.resolver.borrow_mut()
-                            .with_scope(*id,
-            |resolver| {
-                resolver.resolve_str_path_error(DUMMY_SP, &path, false)
-        })?;
-        match ty.def {
-            Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => {
-                let item = cx.tcx.inherent_impls(did).iter()
-                                 .flat_map(|imp| cx.tcx.associated_items(*imp))
-                                 .find(|item| item.ident.name == item_name);
-                if let Some(item) = item {
-                    let out = match item.kind {
-                        ty::AssociatedKind::Method if is_val => "method",
-                        ty::AssociatedKind::Const if is_val => "associatedconstant",
-                        _ => return Err(())
-                    };
-                    Ok((ty.def, Some(format!("{}.{}", out, item_name))))
-                } else {
-                    let is_enum = match ty.def {
-                        Def::Enum(_) => true,
-                        _ => false,
-                    };
-                    let elem = if is_enum {
-                        cx.tcx.adt_def(did).all_fields().find(|item| item.ident.name == item_name)
-                    } else {
-                        cx.tcx.adt_def(did)
-                              .non_enum_variant()
-                              .fields
-                              .iter()
-                              .find(|item| item.ident.name == item_name)
-                    };
-                    if let Some(item) = elem {
-                        Ok((ty.def,
-                            Some(format!("{}.{}",
-                                         if is_enum { "variant" } else { "structfield" },
-                                         item.ident))))
-                    } else {
-                        Err(())
-                    }
-                }
-            }
-            Def::Trait(did) => {
-                let item = cx.tcx.associated_item_def_ids(did).iter()
-                             .map(|item| cx.tcx.associated_item(*item))
-                             .find(|item| item.ident.name == item_name);
-                if let Some(item) = item {
-                    let kind = match item.kind {
-                        ty::AssociatedKind::Const if is_val => "associatedconstant",
-                        ty::AssociatedKind::Type if !is_val => "associatedtype",
-                        ty::AssociatedKind::Method if is_val => {
-                            if item.defaultness.has_value() {
-                                "method"
-                            } else {
-                                "tymethod"
-                            }
-                        }
-                        _ => return Err(())
-                    };
-
-                    Ok((ty.def, Some(format!("{}.{}", kind, item_name))))
-                } else {
-                    Err(())
-                }
-            }
-            _ => Err(())
-        }
-    } else {
-        Err(())
-    }
-}
-
-/// Resolve a string as a macro
-fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
-    use syntax::ext::base::{MacroKind, SyntaxExtension};
-    use syntax::ext::hygiene::Mark;
-    let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
-    let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
-    let mut resolver = cx.resolver.borrow_mut();
-    let mark = Mark::root();
-    let res = resolver
-        .resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false);
-    if let Ok(def) = res {
-        if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
-            return Some(def);
-        }
-    }
-    if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) {
-        return Some(*def);
-    }
-    None
-}
-
-#[derive(Debug)]
-enum PathKind {
-    /// can be either value or type, not a macro
-    Unknown,
-    /// macro
-    Macro,
-    /// values, functions, consts, statics, everything in the value namespace
-    Value,
-    /// types, traits, everything in the type namespace
-    Type,
-}
-
-fn resolution_failure(
-    cx: &DocContext,
-    attrs: &Attributes,
-    path_str: &str,
-    dox: &str,
-    link_range: Option<Range<usize>>,
-) {
-    let sp = span_of_attrs(attrs);
-    let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
-
-    let code_dox = sp.to_src(cx);
-
-    let doc_comment_padding = 3;
-    let mut diag = if let Some(link_range) = link_range {
-        // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
-        //                       ^    ~~~~~~
-        //                       |    link_range
-        //                       last_new_line_offset
-
-        let mut diag;
-        if dox.lines().count() == code_dox.lines().count() {
-            let line_offset = dox[..link_range.start].lines().count();
-            // The span starts in the `///`, so we don't have to account for the leading whitespace
-            let code_dox_len = if line_offset <= 1 {
-                doc_comment_padding
-            } else {
-                // The first `///`
-                doc_comment_padding +
-                    // Each subsequent leading whitespace and `///`
-                    code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
-                        sum + doc_comment_padding + line.len() - line.trim().len()
-                    })
-            };
-
-            // Extract the specific span
-            let sp = sp.from_inner_byte_pos(
-                link_range.start + code_dox_len,
-                link_range.end + code_dox_len,
-            );
-
-            diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-                                                NodeId::new(0),
-                                                sp,
-                                                &msg);
-            diag.span_label(sp, "cannot be resolved, ignoring");
-        } else {
-            diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-                                                NodeId::new(0),
-                                                sp,
-                                                &msg);
-
-            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
-            let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
-
-            // Print the line containing the `link_range` and manually mark it with '^'s
-            diag.note(&format!(
-                "the link appears in this line:\n\n{line}\n\
-                 {indicator: <before$}{indicator:^<found$}",
-                line=line,
-                indicator="",
-                before=link_range.start - last_new_line_offset,
-                found=link_range.len(),
-            ));
-        }
-        diag
-    } else {
-        cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-                                     NodeId::new(0),
-                                     sp,
-                                     &msg)
-    };
-    diag.help("to escape `[` and `]` characters, just add '\\' before them like \
-               `\\[` or `\\]`");
-    diag.emit();
-}
-
 impl Clean<Attributes> for [ast::Attribute] {
     fn clean(&self, cx: &DocContext) -> Attributes {
-        let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self);
-
-        if UnstableFeatures::from_environment().is_nightly_build() {
-            let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
-            for (ori_link, link_range) in markdown_links(&dox) {
-                // bail early for real links
-                if ori_link.contains('/') {
-                    continue;
-                }
-                let link = ori_link.replace("`", "");
-                let (def, fragment) = {
-                    let mut kind = PathKind::Unknown;
-                    let path_str = if let Some(prefix) =
-                        ["struct@", "enum@", "type@",
-                         "trait@", "union@"].iter()
-                                          .find(|p| link.starts_with(**p)) {
-                        kind = PathKind::Type;
-                        link.trim_left_matches(prefix)
-                    } else if let Some(prefix) =
-                        ["const@", "static@",
-                         "value@", "function@", "mod@",
-                         "fn@", "module@", "method@"]
-                            .iter().find(|p| link.starts_with(**p)) {
-                        kind = PathKind::Value;
-                        link.trim_left_matches(prefix)
-                    } else if link.ends_with("()") {
-                        kind = PathKind::Value;
-                        link.trim_right_matches("()")
-                    } else if link.starts_with("macro@") {
-                        kind = PathKind::Macro;
-                        link.trim_left_matches("macro@")
-                    } else if link.ends_with('!') {
-                        kind = PathKind::Macro;
-                        link.trim_right_matches('!')
-                    } else {
-                        &link[..]
-                    }.trim();
-
-                    if path_str.contains(|ch: char| !(ch.is_alphanumeric() ||
-                                                      ch == ':' || ch == '_')) {
-                        continue;
-                    }
-
-                    match kind {
-                        PathKind::Value => {
-                            if let Ok(def) = resolve(cx, path_str, true) {
-                                def
-                            } else {
-                                resolution_failure(cx, &attrs, path_str, &dox, link_range);
-                                // this could just be a normal link or a broken link
-                                // we could potentially check if something is
-                                // "intra-doc-link-like" and warn in that case
-                                continue;
-                            }
-                        }
-                        PathKind::Type => {
-                            if let Ok(def) = resolve(cx, path_str, false) {
-                                def
-                            } else {
-                                resolution_failure(cx, &attrs, path_str, &dox, link_range);
-                                // this could just be a normal link
-                                continue;
-                            }
-                        }
-                        PathKind::Unknown => {
-                            // try everything!
-                            if let Some(macro_def) = macro_resolve(cx, path_str) {
-                                if let Ok(type_def) = resolve(cx, path_str, false) {
-                                    let (type_kind, article, type_disambig)
-                                        = type_ns_kind(type_def.0, path_str);
-                                    ambiguity_error(cx, &attrs, path_str,
-                                                    article, type_kind, &type_disambig,
-                                                    "a", "macro", &format!("macro@{}", path_str));
-                                    continue;
-                                } else if let Ok(value_def) = resolve(cx, path_str, true) {
-                                    let (value_kind, value_disambig)
-                                        = value_ns_kind(value_def.0, path_str)
-                                            .expect("struct and mod cases should have been \
-                                                     caught in previous branch");
-                                    ambiguity_error(cx, &attrs, path_str,
-                                                    "a", value_kind, &value_disambig,
-                                                    "a", "macro", &format!("macro@{}", path_str));
-                                }
-                                (macro_def, None)
-                            } else if let Ok(type_def) = resolve(cx, path_str, false) {
-                                // It is imperative we search for not-a-value first
-                                // Otherwise we will find struct ctors for when we are looking
-                                // for structs, and the link won't work.
-                                // if there is something in both namespaces
-                                if let Ok(value_def) = resolve(cx, path_str, true) {
-                                    let kind = value_ns_kind(value_def.0, path_str);
-                                    if let Some((value_kind, value_disambig)) = kind {
-                                        let (type_kind, article, type_disambig)
-                                            = type_ns_kind(type_def.0, path_str);
-                                        ambiguity_error(cx, &attrs, path_str,
-                                                        article, type_kind, &type_disambig,
-                                                        "a", value_kind, &value_disambig);
-                                        continue;
-                                    }
-                                }
-                                type_def
-                            } else if let Ok(value_def) = resolve(cx, path_str, true) {
-                                value_def
-                            } else {
-                                resolution_failure(cx, &attrs, path_str, &dox, link_range);
-                                // this could just be a normal link
-                                continue;
-                            }
-                        }
-                        PathKind::Macro => {
-                            if let Some(def) = macro_resolve(cx, path_str) {
-                                (def, None)
-                            } else {
-                                resolution_failure(cx, &attrs, path_str, &dox, link_range);
-                                continue
-                            }
-                        }
-                    }
-                };
-
-                if let Def::PrimTy(_) = def {
-                    attrs.links.push((ori_link, None, fragment));
-                } else {
-                    let id = register_def(cx, def);
-                    attrs.links.push((ori_link, Some(id), fragment));
-                }
-            }
-
-            cx.sess().abort_if_errors();
-        }
-
-        attrs
+        Attributes::from_ast(cx.sess().diagnostic(), self)
     }
 }
 
@@ -1724,7 +1227,7 @@ fn clean(&self, _: &DocContext) -> Lifetime {
                         hir::GenericBound::Outlives(lt) => lt,
                         _ => panic!(),
                     });
-                    let name = bounds.next().unwrap().name.ident();
+                    let name = bounds.next().expect("no more bounds").name.ident();
                     let mut s = format!("{}: {}", self.name.ident(), name);
                     for bound in bounds {
                         s.push_str(&format!(" + {}", bound.name.ident()));
@@ -1837,8 +1340,8 @@ impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region<'tcx>, ty:
     fn clean(&self, cx: &DocContext) -> WherePredicate {
         let ty::OutlivesPredicate(ref a, ref b) = *self;
         WherePredicate::RegionPredicate {
-            lifetime: a.clean(cx).unwrap(),
-            bounds: vec![GenericBound::Outlives(b.clean(cx).unwrap())]
+            lifetime: a.clean(cx).expect("failed to clean lifetime"),
+            bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))]
         }
     }
 }
@@ -1849,7 +1352,7 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
 
         WherePredicate::BoundPredicate {
             ty: ty.clean(cx),
-            bounds: vec![GenericBound::Outlives(lt.clean(cx).unwrap())]
+            bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))]
         }
     }
 }
@@ -1943,7 +1446,7 @@ fn clean(&self, cx: &DocContext) -> GenericParamDef {
                         hir::GenericBound::Outlives(lt) => lt,
                         _ => panic!(),
                     });
-                    let name = bounds.next().unwrap().name.ident();
+                    let name = bounds.next().expect("no more bounds").name.ident();
                     let mut s = format!("{}: {}", self.name.ident(), name);
                     for bound in bounds {
                         s.push_str(&format!(" + {}", bound.name.ident()));
@@ -2158,7 +1661,6 @@ fn clean(&self, cx: &DocContext) -> Item {
             (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
         });
 
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -2333,7 +1835,6 @@ pub struct Trait {
 
 impl Clean<Item> for doctree::Trait {
     fn clean(&self, cx: &DocContext) -> Item {
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         let attrs = self.attrs.clean(cx);
         let is_spotlight = attrs.has_doc_flag("spotlight");
         Item {
@@ -2405,7 +1906,6 @@ fn clean(&self, cx: &DocContext) -> Item {
                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
             }
         };
-        *cx.current_item_name.borrow_mut() = Some(self.ident.name);
         Item {
             name: Some(self.ident.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -2438,7 +1938,6 @@ fn clean(&self, cx: &DocContext) -> Item {
                 generics: Generics::default(),
             }, true),
         };
-        *cx.current_item_name.borrow_mut() = Some(self.ident.name);
         Item {
             name: Some(self.ident.name.clean(cx)),
             source: self.span.clean(cx),
@@ -2929,7 +2428,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                 };
 
                 if let Some(&hir::ItemKind::Ty(ref ty, ref generics)) = alias {
-                    let provided_params = &path.segments.last().unwrap();
+                    let provided_params = &path.segments.last().expect("segments were empty");
                     let mut ty_substs = FxHashMap();
                     let mut lt_substs = FxHashMap();
                     provided_params.with_generic_args(|generic_args| {
@@ -3002,7 +2501,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     segments: segments.into(),
                 };
                 Type::QPath {
-                    name: p.segments.last().unwrap().ident.name.clean(cx),
+                    name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
                     self_type: box qself.clean(cx),
                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
                 }
@@ -3058,7 +2557,7 @@ fn clean(&self, cx: &DocContext) -> Type {
             ty::TyStr => Primitive(PrimitiveType::Str),
             ty::TySlice(ty) => Slice(box ty.clean(cx)),
             ty::TyArray(ty, n) => {
-                let mut n = cx.tcx.lift(&n).unwrap();
+                let mut n = cx.tcx.lift(&n).expect("array lift failed");
                 if let ConstValue::Unevaluated(def_id, substs) = n.val {
                     let param_env = cx.tcx.param_env(def_id);
                     let cid = GlobalId {
@@ -3080,7 +2579,7 @@ fn clean(&self, cx: &DocContext) -> Type {
             },
             ty::TyFnDef(..) |
             ty::TyFnPtr(_) => {
-                let ty = cx.tcx.lift(self).unwrap();
+                let ty = cx.tcx.lift(self).expect("TyFnPtr lift failed");
                 let sig = ty.fn_sig(cx.tcx);
                 BareFunction(box BareFunctionDecl {
                     unsafety: sig.unsafety(),
@@ -3171,7 +2670,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                 // by looking up the projections associated with the def_id.
                 let predicates_of = cx.tcx.predicates_of(def_id);
-                let substs = cx.tcx.lift(&substs).unwrap();
+                let substs = cx.tcx.lift(&substs).expect("TyAnon lift failed");
                 let bounds = predicates_of.instantiate(cx.tcx, substs);
                 let mut regions = vec![];
                 let mut has_sized = false;
@@ -3232,7 +2731,6 @@ fn clean(&self, cx: &DocContext) -> Type {
 
 impl Clean<Item> for hir::StructField {
     fn clean(&self, cx: &DocContext) -> Item {
-        *cx.current_item_name.borrow_mut() = Some(self.ident.name);
         Item {
             name: Some(self.ident.name).clean(cx),
             attrs: self.attrs.clean(cx),
@@ -3310,8 +2808,8 @@ impl Clean<Vec<Item>> for doctree::Struct {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         let name = self.name.clean(cx);
         let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
+        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
 
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         ret.push(Item {
             name: Some(name),
             attrs: self.attrs.clean(cx),
@@ -3336,8 +2834,8 @@ impl Clean<Vec<Item>> for doctree::Union {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         let name = self.name.clean(cx);
         let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
+        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
 
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         ret.push(Item {
             name: Some(name),
             attrs: self.attrs.clean(cx),
@@ -3389,8 +2887,8 @@ impl Clean<Vec<Item>> for doctree::Enum {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         let name = self.name.clean(cx);
         let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
+        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
 
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         ret.push(Item {
             name: Some(name),
             attrs: self.attrs.clean(cx),
@@ -3417,7 +2915,6 @@ pub struct Variant {
 
 impl Clean<Item> for doctree::Variant {
     fn clean(&self, cx: &DocContext) -> Item {
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3541,7 +3038,7 @@ pub struct Path {
 
 impl Path {
     pub fn last_name(&self) -> &str {
-        self.segments.last().unwrap().name.as_str()
+        self.segments.last().expect("segments were empty").name.as_str()
     }
 }
 
@@ -3698,7 +3195,6 @@ pub struct Typedef {
 
 impl Clean<Item> for doctree::Typedef {
     fn clean(&self, cx: &DocContext) -> Item {
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3774,7 +3270,6 @@ pub struct Static {
 impl Clean<Item> for doctree::Static {
     fn clean(&self, cx: &DocContext) -> Item {
         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3800,7 +3295,6 @@ pub struct Constant {
 
 impl Clean<Item> for doctree::Constant {
     fn clean(&self, cx: &DocContext) -> Item {
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -3871,21 +3365,15 @@ pub fn get_auto_traits_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
     finder.get_with_def_id(id)
 }
 
-fn get_name_if_possible(cx: &DocContext, node: NodeId) -> Option<Name> {
-    match cx.tcx.hir.get(node) {
-        Node::NodeItem(_) |
-        Node::NodeForeignItem(_) |
-        Node::NodeImplItem(_) |
-        Node::NodeTraitItem(_) |
-        Node::NodeVariant(_) |
-        Node::NodeField(_) |
-        Node::NodeLifetime(_) |
-        Node::NodeGenericParam(_) |
-        Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_,_,_,_), .. }) |
-        Node::NodeStructCtor(_) => {}
-        _ => return None,
-    }
-    Some(cx.tcx.hir.name(node))
+pub fn get_blanket_impls_with_node_id(cx: &DocContext, id: ast::NodeId, name: String) -> Vec<Item> {
+    let finder = BlanketImplFinder::new(cx);
+    finder.get_with_node_id(id, name)
+}
+
+pub fn get_blanket_impls_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
+    let finder = BlanketImplFinder::new(cx);
+
+    finder.get_with_def_id(id)
 }
 
 impl Clean<Vec<Item>> for doctree::Impl {
@@ -3907,7 +3395,6 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
                   .collect()
         }).unwrap_or(FxHashSet());
 
-        *cx.current_item_name.borrow_mut() = get_name_if_possible(cx, self.for_.id);
         ret.push(Item {
             name: None,
             attrs: self.attrs.clean(cx),
@@ -3995,7 +3482,6 @@ fn build_deref_target_impls(cx: &DocContext,
 
 impl Clean<Item> for doctree::ExternCrate {
     fn clean(&self, cx: &DocContext) -> Item {
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: None,
             attrs: self.attrs.clean(cx),
@@ -4043,7 +3529,6 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
             Import::Simple(name.clean(cx), resolve_use_source(cx, path))
         };
 
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         vec![Item {
             name: None,
             attrs: self.attrs.clean(cx),
@@ -4113,7 +3598,6 @@ fn clean(&self, cx: &DocContext) -> Item {
             }
         };
 
-        *cx.current_item_name.borrow_mut() = Some(self.name);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -4129,7 +3613,7 @@ fn clean(&self, cx: &DocContext) -> Item {
 
 // Utilities
 
-trait ToSource {
+pub trait ToSource {
     fn to_src(&self, cx: &DocContext) -> String;
 }
 
@@ -4192,7 +3676,7 @@ fn print_const(cx: &DocContext, n: &ty::Const) -> String {
         },
         _ => {
             let mut s = String::new();
-            ::rustc::mir::fmt_const_val(&mut s, n).unwrap();
+            ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
             // array lengths are obviously usize
             if s.ends_with("usize") {
                 let n = s.len() - "usize".len();
@@ -4239,7 +3723,7 @@ fn resolve_type(cx: &DocContext,
     ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
 }
 
-fn register_def(cx: &DocContext, def: Def) -> DefId {
+pub fn register_def(cx: &DocContext, def: Def) -> DefId {
     debug!("register_def({:?})", def);
 
     let (did, kind) = match def {
@@ -4253,7 +3737,8 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
         Def::TyForeign(i) => (i, TypeKind::Foreign),
         Def::Const(i) => (i, TypeKind::Const),
         Def::Static(i, _) => (i, TypeKind::Static),
-        Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
+        Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
+                            TypeKind::Enum),
         Def::Macro(i, _) => (i, TypeKind::Macro),
         Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
         Def::SelfTy(_, Some(impl_def_id)) => {
@@ -4289,7 +3774,6 @@ pub struct Macro {
 impl Clean<Item> for doctree::Macro {
     fn clean(&self, cx: &DocContext) -> Item {
         let name = self.name.clean(cx);
-        *cx.current_item_name.borrow_mut() = None;
         Item {
             name: Some(name.clone()),
             attrs: self.attrs.clean(cx),
@@ -4482,7 +3966,7 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> {
     }
 }
 
-fn get_path_for_type<F>(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path
+pub fn get_path_for_type<F>(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path
 where F: Fn(DefId) -> Def {
     struct AbsolutePathBuffer {
         names: Vec<String>,
index 30a55bf0d18092f112df492ec5356e51f01bf1bb..9ea8bc536352a2d61d8458f7ec4cca7e042a811d 100644 (file)
@@ -96,7 +96,7 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
             if !trait_is_same_or_supertrait(cx, did, trait_did) {
                 return false
             }
-            let last = path.segments.last_mut().unwrap();
+            let last = path.segments.last_mut().expect("segments were empty");
             match last.args {
                 PP::AngleBracketed { ref mut bindings, .. } => {
                     bindings.push(clean::TypeBinding {
index 769c9804a355ae6a9455a3cff2ad55d82ce0036d..86e5bbeab706a2dafa72c089270bd171ec9373df 100644 (file)
@@ -11,8 +11,9 @@
 use rustc_lint;
 use rustc_driver::{self, driver, target_features, abort_on_err};
 use rustc::session::{self, config};
-use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
+use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CrateNum, LOCAL_CRATE};
 use rustc::hir::def::Def;
+use rustc::hir::{self, HirVec};
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{self, TyCtxt, AllArenas};
 use rustc_metadata::cstore::CStore;
 use rustc_target::spec::TargetTriple;
 
-use syntax::ast::{Name, NodeId};
+use syntax::ast::{self, Ident};
 use syntax::codemap;
 use syntax::edition::Edition;
 use syntax::feature_gate::UnstableFeatures;
 use syntax::json::JsonEmitter;
+use syntax::ptr::P;
+use syntax::symbol::keywords;
+use syntax_pos::DUMMY_SP;
 use errors;
 use errors::emitter::{Emitter, EmitterWriter};
 
 
 use visit_ast::RustdocVisitor;
 use clean;
-use clean::Clean;
+use clean::{get_path_for_type, Clean, MAX_DEF_ID, AttributesExt};
 use html::render::RenderInfo;
+use passes;
 
-pub use rustc::session::config::{Input, CodegenOptions};
+pub use rustc::session::config::{Input, Options, CodegenOptions};
 pub use rustc::session::search_paths::SearchPaths;
 
 pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
 
-pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
+pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
+    pub resolver: &'a RefCell<resolve::Resolver<'rcx, 'cstore>>,
     /// The stack of module NodeIds up till this point
-    pub mod_ids: RefCell<Vec<NodeId>>,
     pub crate_name: Option<String>,
-    pub cstore: Rc<dyn CrateStore>,
+    pub cstore: Rc<CStore>,
     pub populated_all_crate_impls: Cell<bool>,
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
@@ -83,11 +87,10 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
     pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
     /// Maps (type_id, trait_id) -> auto trait impl
     pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>,
-    pub current_item_name: RefCell<Option<Name>>,
     pub all_traits: Vec<DefId>,
 }
 
-impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
+impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> {
     pub fn sess(&self) -> &session::Session {
         &self.tcx.sess
     }
@@ -107,6 +110,140 @@ pub fn enter_alias<F, R>(&self,
         *self.lt_substs.borrow_mut() = old_lts;
         r
     }
+
+    // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly
+    // refactoring either librustdoc or librustc. In particular, allowing new DefIds to be
+    // registered after the AST is constructed would require storing the defid mapping in a
+    // RefCell, decreasing the performance for normal compilation for very little gain.
+    //
+    // Instead, we construct 'fake' def ids, which start immediately after the last DefId in
+    // DefIndexAddressSpace::Low. In the Debug impl for clean::Item, we explicitly check for fake
+    // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds
+    pub fn next_def_id(&self, crate_num: CrateNum) -> DefId {
+        let start_def_id = {
+            let next_id = if crate_num == LOCAL_CRATE {
+                self.tcx
+                    .hir
+                    .definitions()
+                    .def_path_table()
+                    .next_id(DefIndexAddressSpace::Low)
+            } else {
+                self.cstore
+                    .def_path_table(crate_num)
+                    .next_id(DefIndexAddressSpace::Low)
+            };
+
+            DefId {
+                krate: crate_num,
+                index: next_id,
+            }
+        };
+
+        let mut fake_ids = self.fake_def_ids.borrow_mut();
+
+        let def_id = fake_ids.entry(crate_num).or_insert(start_def_id).clone();
+        fake_ids.insert(
+            crate_num,
+            DefId {
+                krate: crate_num,
+                index: DefIndex::from_array_index(
+                    def_id.index.as_array_index() + 1,
+                    def_id.index.address_space(),
+                ),
+            },
+        );
+
+        MAX_DEF_ID.with(|m| {
+            m.borrow_mut()
+                .entry(def_id.krate.clone())
+                .or_insert(start_def_id);
+        });
+
+        self.all_fake_def_ids.borrow_mut().insert(def_id);
+
+        def_id.clone()
+    }
+
+    pub fn get_real_ty<F>(&self,
+                          def_id: DefId,
+                          def_ctor: &F,
+                          real_name: &Option<Ident>,
+                          generics: &ty::Generics,
+    ) -> hir::Ty
+    where F: Fn(DefId) -> Def {
+        let path = get_path_for_type(self.tcx, def_id, def_ctor);
+        let mut segments = path.segments.into_vec();
+        let last = segments.pop().expect("segments were empty");
+
+        segments.push(hir::PathSegment::new(
+            real_name.unwrap_or(last.ident),
+            self.generics_to_path_params(generics.clone()),
+            false,
+        ));
+
+        let new_path = hir::Path {
+            span: path.span,
+            def: path.def,
+            segments: HirVec::from_vec(segments),
+        };
+
+        hir::Ty {
+            id: ast::DUMMY_NODE_ID,
+            node: hir::TyKind::Path(hir::QPath::Resolved(None, P(new_path))),
+            span: DUMMY_SP,
+            hir_id: hir::DUMMY_HIR_ID,
+        }
+    }
+
+    pub fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs {
+        let mut args = vec![];
+
+        for param in generics.params.iter() {
+            match param.kind {
+                ty::GenericParamDefKind::Lifetime => {
+                    let name = if param.name == "" {
+                        hir::ParamName::Plain(keywords::StaticLifetime.ident())
+                    } else {
+                        hir::ParamName::Plain(ast::Ident::from_interned_str(param.name))
+                    };
+
+                    args.push(hir::GenericArg::Lifetime(hir::Lifetime {
+                        id: ast::DUMMY_NODE_ID,
+                        span: DUMMY_SP,
+                        name: hir::LifetimeName::Param(name),
+                    }));
+                }
+                ty::GenericParamDefKind::Type {..} => {
+                    args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone())));
+                }
+            }
+        }
+
+        hir::GenericArgs {
+            args: HirVec::from_vec(args),
+            bindings: HirVec::new(),
+            parenthesized: false,
+        }
+    }
+
+    pub fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty {
+        debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id);
+        hir::Ty {
+            id: ast::DUMMY_NODE_ID,
+            node: hir::TyKind::Path(hir::QPath::Resolved(
+                None,
+                P(hir::Path {
+                    span: DUMMY_SP,
+                    def: Def::TyParam(param.def_id),
+                    segments: HirVec::from_vec(vec![
+                        hir::PathSegment::from_ident(Ident::from_interned_str(param.name))
+                    ]),
+                }),
+            )),
+            span: DUMMY_SP,
+            hir_id: hir::DUMMY_HIR_ID,
+        }
+    }
 }
 
 pub trait DocAccessLevels {
@@ -128,7 +265,7 @@ pub fn new_handler(error_format: ErrorOutputType, codemap: Option<Lrc<codemap::C
 {
     // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
     // stick to the defaults
-    let sessopts = config::basic_options();
+    let sessopts = Options::default();
     let emitter: Box<dyn Emitter + sync::Send> = match error_format {
         ErrorOutputType::HumanReadable(color_config) => Box::new(
             EmitterWriter::stderr(
@@ -184,7 +321,10 @@ pub fn run_core(search_paths: SearchPaths,
                 error_format: ErrorOutputType,
                 cmd_lints: Vec<(String, lint::Level)>,
                 lint_cap: Option<lint::Level>,
-                describe_lints: bool) -> (clean::Crate, RenderInfo)
+                describe_lints: bool,
+                mut manual_passes: Vec<String>,
+                mut default_passes: passes::DefaultPassOption)
+    -> (clean::Crate, RenderInfo, Vec<String>)
 {
     // Parse, resolve, and typecheck the given crate.
 
@@ -224,7 +364,7 @@ pub fn run_core(search_paths: SearchPaths,
     let sessopts = config::Options {
         maybe_sysroot,
         search_paths,
-        crate_types: vec![config::CrateTypeRlib],
+        crate_types: vec![config::CrateType::Rlib],
         lint_opts: if !allow_warnings {
             lints
         } else {
@@ -244,7 +384,7 @@ pub fn run_core(search_paths: SearchPaths,
         error_format,
         edition,
         describe_lints,
-        ..config::basic_options()
+        ..Options::default()
     };
     driver::spawn_thread_pool(sessopts, move |sessopts| {
         let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
@@ -379,23 +519,86 @@ pub fn run_core(search_paths: SearchPaths,
                 ty_substs: Default::default(),
                 lt_substs: Default::default(),
                 impl_trait_bounds: Default::default(),
-                mod_ids: Default::default(),
                 send_trait: send_trait,
                 fake_def_ids: RefCell::new(FxHashMap()),
                 all_fake_def_ids: RefCell::new(FxHashSet()),
                 generated_synthetics: RefCell::new(FxHashSet()),
-                current_item_name: RefCell::new(None),
                 all_traits: tcx.all_traits(LOCAL_CRATE).to_vec(),
             };
             debug!("crate: {:?}", tcx.hir.krate());
 
-            let krate = {
+            let mut krate = {
                 let mut v = RustdocVisitor::new(&ctxt);
                 v.visit(tcx.hir.krate());
                 v.clean(&ctxt)
             };
 
-            (krate, ctxt.renderinfo.into_inner())
+            fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
+                let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \
+                                                         considered deprecated", name));
+                msg.warn("please see https://github.com/rust-lang/rust/issues/44136");
+
+                if name == "no_default_passes" {
+                    msg.help("you may want to use `#![doc(document_private_items)]`");
+                }
+
+                msg.emit();
+            }
+
+            // Process all of the crate attributes, extracting plugin metadata along
+            // with the passes which we are supposed to run.
+            for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
+                let diag = ctxt.sess().diagnostic();
+
+                let name = attr.name().map(|s| s.as_str());
+                let name = name.as_ref().map(|s| &s[..]);
+                if attr.is_word() {
+                    if name == Some("no_default_passes") {
+                        report_deprecated_attr("no_default_passes", diag);
+                        if default_passes == passes::DefaultPassOption::Default {
+                            default_passes = passes::DefaultPassOption::None;
+                        }
+                    }
+                } else if let Some(value) = attr.value_str() {
+                    let sink = match name {
+                        Some("passes") => {
+                            report_deprecated_attr("passes = \"...\"", diag);
+                            &mut manual_passes
+                        },
+                        Some("plugins") => {
+                            report_deprecated_attr("plugins = \"...\"", diag);
+                            eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \
+                                      see CVE-2018-1000622");
+                            continue
+                        },
+                        _ => continue,
+                    };
+                    for p in value.as_str().split_whitespace() {
+                        sink.push(p.to_string());
+                    }
+                }
+
+                if attr.is_word() && name == Some("document_private_items") {
+                    if default_passes == passes::DefaultPassOption::Default {
+                        default_passes = passes::DefaultPassOption::Private;
+                    }
+                }
+            }
+
+            let mut passes: Vec<String> =
+                passes::defaults(default_passes).iter().map(|p| p.to_string()).collect();
+            passes.extend(manual_passes);
+
+            for pass in &passes {
+                // the "unknown pass" error will be reported when late passes are run
+                if let Some(pass) = passes::find_pass(pass).and_then(|p| p.early_fn()) {
+                    krate = pass(krate, &ctxt);
+                }
+            }
+
+            ctxt.sess().abort_if_errors();
+
+            (krate, ctxt.renderinfo.into_inner(), passes)
         }), &sess)
     })
 }
index 10b6c9850ae7773dc99d20972ce918c9f42570cc..9631ea059cc4300f0337ac755716024033e3133a 100644 (file)
@@ -12,7 +12,9 @@
 use std::path::Path;
 use std::str;
 use errors;
-use html::markdown::Markdown;
+use syntax::feature_gate::UnstableFeatures;
+use html::markdown::{IdMap, ErrorCodes, Markdown};
+use std::cell::RefCell;
 
 #[derive(Clone)]
 pub struct ExternalHtml {
@@ -29,8 +31,10 @@ pub struct ExternalHtml {
 
 impl ExternalHtml {
     pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
-                md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler)
+                md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler,
+                id_map: &mut IdMap)
             -> Option<ExternalHtml> {
+        let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
         load_external_files(in_header, diag)
             .and_then(|ih|
                 load_external_files(before_content, diag)
@@ -38,7 +42,8 @@ pub fn load(in_header: &[String], before_content: &[String], after_content: &[St
             )
             .and_then(|(ih, bc)|
                 load_external_files(md_before_content, diag)
-                    .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[]))))
+                    .map(|m_bc| (ih,
+                            format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes))))
             )
             .and_then(|(ih, bc)|
                 load_external_files(after_content, diag)
@@ -46,7 +51,8 @@ pub fn load(in_header: &[String], before_content: &[String], after_content: &[St
             )
             .and_then(|(ih, bc, ac)|
                 load_external_files(md_after_content, diag)
-                    .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[]))))
+                    .map(|m_ac| (ih, bc,
+                            format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), codes))))
             )
             .map(|(ih, bc, ac)|
                 ExternalHtml {
index 065778d8d0725f5a49c5b84db2413d7b25e4c58a..73d7a9ab8599d75015d62301eeb2c21e1cdddc3b 100644 (file)
 //! This module uses libsyntax's lexer to provide token-based highlighting for
 //! the HTML documentation generated by rustdoc.
 //!
-//! If you just want to syntax highlighting for a Rust program, then you can use
-//! the `render_inner_with_highlighting` or `render_with_highlighting`
-//! functions. For more advanced use cases (if you want to supply your own css
-//! classes or control how the HTML is generated, or even generate something
-//! other then HTML), then you should implement the `Writer` trait and use a
-//! `Classifier`.
+//! Use the `render_with_highlighting` to highlight some rust code.
 
 use html::escape::Escape;
 
@@ -33,7 +28,7 @@
 use syntax_pos::{Span, FileName};
 
 /// Highlights `src`, returning the HTML output.
-pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>,
+pub fn render_with_highlighting(src: &str, class: Option<&str>,
                                 extension: Option<&str>,
                                 tooltip: Option<(&str, &str)>) -> String {
     debug!("highlighting: ================\n{}\n==============", src);
@@ -46,7 +41,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>
                      class='tooltiptext'>{}</span></div></div>",
                class, tooltip).unwrap();
     }
-    write_header(class, id, &mut out).unwrap();
+    write_header(class, &mut out).unwrap();
 
     let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), sess.codemap());
     if let Err(_) = classifier.write_source(&mut out) {
@@ -63,7 +58,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>
 /// Processes a program (nested in the internal `lexer`), classifying strings of
 /// text by highlighting category (`Class`). Calls out to a `Writer` to write
 /// each span of text in sequence.
-pub struct Classifier<'a> {
+struct Classifier<'a> {
     lexer: lexer::StringReader<'a>,
     codemap: &'a CodeMap,
 
@@ -75,7 +70,7 @@ pub struct Classifier<'a> {
 
 /// How a span of text is classified. Mostly corresponds to token kinds.
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum Class {
+enum Class {
     None,
     Comment,
     DocComment,
@@ -103,7 +98,7 @@ pub enum Class {
 /// The classifier will call into the `Writer` implementation as it finds spans
 /// of text to highlight. Exactly how that text should be highlighted is up to
 /// the implementation.
-pub trait Writer {
+trait Writer {
     /// Called when we start processing a span of text that should be highlighted.
     /// The `Class` argument specifies how it should be highlighted.
     fn enter_span(&mut self, _: Class) -> io::Result<()>;
@@ -111,11 +106,9 @@ pub trait Writer {
     /// Called at the end of a span of highlighted text.
     fn exit_span(&mut self) -> io::Result<()>;
 
-    /// Called for a span of text, usually, but not always, a single token. If
-    /// the string of text (`T`) does correspond to a token, then the token will
-    /// also be passed. If the text should be highlighted differently from the
-    /// surrounding text, then the `Class` argument will be a value other than
-    /// `None`.
+    /// Called for a span of text.  If the text should be highlighted differently from the
+    /// surrounding text, then the `Class` argument will be a value other than `None`.
+    ///
     /// The following sequences of callbacks are equivalent:
     /// ```plain
     ///     enter_span(Foo), string("text", None), exit_span()
@@ -125,8 +118,7 @@ pub trait Writer {
     /// more flexible.
     fn string<T: Display>(&mut self,
                           text: T,
-                          klass: Class,
-                          tok: Option<&TokenAndSpan>)
+                          klass: Class)
                           -> io::Result<()>;
 }
 
@@ -135,8 +127,7 @@ fn string<T: Display>(&mut self,
 impl<U: Write> Writer for U {
     fn string<T: Display>(&mut self,
                           text: T,
-                          klass: Class,
-                          _tas: Option<&TokenAndSpan>)
+                          klass: Class)
                           -> io::Result<()> {
         match klass {
             Class::None => write!(self, "{}", text),
@@ -154,7 +145,7 @@ fn exit_span(&mut self) -> io::Result<()> {
 }
 
 impl<'a> Classifier<'a> {
-    pub fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> {
+    fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> {
         Classifier {
             lexer,
             codemap,
@@ -186,7 +177,7 @@ fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
     /// is used. All source code emission is done as slices from the source map,
     /// not from the tokens themselves, in order to stay true to the original
     /// source.
-    pub fn write_source<W: Writer>(&mut self,
+    fn write_source<W: Writer>(&mut self,
                                    out: &mut W)
                                    -> io::Result<()> {
         loop {
@@ -208,7 +199,7 @@ fn write_token<W: Writer>(&mut self,
                               -> io::Result<()> {
         let klass = match tas.tok {
             token::Shebang(s) => {
-                out.string(Escape(&s.as_str()), Class::None, Some(&tas))?;
+                out.string(Escape(&s.as_str()), Class::None)?;
                 return Ok(());
             },
 
@@ -272,8 +263,8 @@ fn write_token<W: Writer>(&mut self,
                         self.in_attribute = true;
                         out.enter_span(Class::Attribute)?;
                     }
-                    out.string("#", Class::None, None)?;
-                    out.string("!", Class::None, None)?;
+                    out.string("#", Class::None)?;
+                    out.string("!", Class::None)?;
                     return Ok(());
                 }
 
@@ -282,13 +273,13 @@ fn write_token<W: Writer>(&mut self,
                     self.in_attribute = true;
                     out.enter_span(Class::Attribute)?;
                 }
-                out.string("#", Class::None, None)?;
+                out.string("#", Class::None)?;
                 return Ok(());
             }
             token::CloseDelim(token::Bracket) => {
                 if self.in_attribute {
                     self.in_attribute = false;
-                    out.string("]", Class::None, None)?;
+                    out.string("]", Class::None)?;
                     out.exit_span()?;
                     return Ok(());
                 } else {
@@ -344,7 +335,7 @@ fn write_token<W: Writer>(&mut self,
 
         // Anything that didn't return above is the simple case where we the
         // class just spans a single token, so we can use the `string` method.
-        out.string(Escape(&self.snip(tas.sp)), klass, Some(&tas))
+        out.string(Escape(&self.snip(tas.sp)), klass)
     }
 
     // Helper function to get a snippet from the codemap.
@@ -355,7 +346,7 @@ fn snip(&self, sp: Span) -> String {
 
 impl Class {
     /// Returns the css class expected by rustdoc for each `Class`.
-    pub fn rustdoc_class(self) -> &'static str {
+    fn rustdoc_class(self) -> &'static str {
         match self {
             Class::None => "",
             Class::Comment => "comment",
@@ -379,15 +370,8 @@ pub fn rustdoc_class(self) -> &'static str {
     }
 }
 
-fn write_header(class: Option<&str>,
-                id: Option<&str>,
-                out: &mut dyn Write)
-                -> io::Result<()> {
-    write!(out, "<pre ")?;
-    if let Some(id) = id {
-        write!(out, "id='{}' ", id)?;
-    }
-    write!(out, "class=\"rust {}\">\n", class.unwrap_or(""))
+fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> {
+    write!(out, "<pre class=\"rust {}\">\n", class.unwrap_or(""))
 }
 
 fn write_footer(out: &mut dyn Write) -> io::Result<()> {
index 8d85adfb3d0ff3a052dc317642808d32c550041f..b22e239e20a0eeaf166b3b34935ceb6eaaed5655 100644 (file)
 //! ```
 //! #![feature(rustc_private)]
 //!
-//! use rustdoc::html::markdown::Markdown;
+//! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes};
+//! use std::cell::RefCell;
 //!
 //! let s = "My *markdown* _text_";
-//! let html = format!("{}", Markdown(s, &[]));
+//! let mut id_map = IdMap::new();
+//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), ErrorCodes::Yes));
 //! // ... something using html
 //! ```
 
 #![allow(non_camel_case_types)]
 
-use rustc::session;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
 use std::borrow::Cow;
 use std::ops::Range;
 use std::str;
-use syntax::feature_gate::UnstableFeatures;
-use syntax::codemap::Span;
 
-use html::render::derive_id;
 use html::toc::TocBuilder;
 use html::highlight;
 use test;
 /// formatted, this struct will emit the HTML corresponding to the rendered
 /// version of the contained markdown string.
 /// The second parameter is a list of link replacements
-pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)]);
+pub struct Markdown<'a>(
+    pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders the markdown with a
 /// table of contents.
-pub struct MarkdownWithToc<'a>(pub &'a str);
+pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
-pub struct MarkdownHtml<'a>(pub &'a str);
+pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders only the first paragraph.
 pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum ErrorCodes {
+    Yes,
+    No,
+}
+
+impl ErrorCodes {
+    pub fn from(b: bool) -> Self {
+        match b {
+            true => ErrorCodes::Yes,
+            false => ErrorCodes::No,
+        }
+    }
+
+    pub fn as_bool(self) -> bool {
+        match self {
+            ErrorCodes::Yes => true,
+            ErrorCodes::No => false,
+        }
+    }
+}
+
 /// Controls whether a line will be hidden or shown in HTML output.
 ///
 /// All lines are used in documentation tests.
@@ -129,12 +150,14 @@ fn slugify(c: char) -> Option<char> {
 /// Adds syntax highlighting and playground Run buttons to rust code blocks.
 struct CodeBlocks<'a, I: Iterator<Item = Event<'a>>> {
     inner: I,
+    check_error_codes: ErrorCodes,
 }
 
 impl<'a, I: Iterator<Item = Event<'a>>> CodeBlocks<'a, I> {
-    fn new(iter: I) -> Self {
+    fn new(iter: I, error_codes: ErrorCodes) -> Self {
         CodeBlocks {
             inner: iter,
+            check_error_codes: error_codes,
         }
     }
 }
@@ -147,7 +170,7 @@ fn next(&mut self) -> Option<Self::Item> {
         let compile_fail;
         let ignore;
         if let Some(Event::Start(Tag::CodeBlock(lang))) = event {
-            let parse_result = LangString::parse(&lang);
+            let parse_result = LangString::parse(&lang, self.check_error_codes);
             if !parse_result.rust {
                 return Some(Event::Start(Tag::CodeBlock(lang)));
             }
@@ -224,7 +247,6 @@ fn dont_escape(c: u8) -> bool {
                                       if ignore { " ignore" }
                                       else if compile_fail { " compile_fail" }
                                       else { "" })),
-                        None,
                         playground_button.as_ref().map(String::as_str),
                         tooltip));
             Some(Event::Html(s.into()))
@@ -266,23 +288,25 @@ fn next(&mut self) -> Option<Self::Item> {
 }
 
 /// Make headings links with anchor ids and build up TOC.
-struct HeadingLinks<'a, 'b, I: Iterator<Item = Event<'a>>> {
+struct HeadingLinks<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> {
     inner: I,
     toc: Option<&'b mut TocBuilder>,
     buf: VecDeque<Event<'a>>,
+    id_map: &'ids mut IdMap,
 }
 
-impl<'a, 'b, I: Iterator<Item = Event<'a>>> HeadingLinks<'a, 'b, I> {
-    fn new(iter: I, toc: Option<&'b mut TocBuilder>) -> Self {
+impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> HeadingLinks<'a, 'b, 'ids, I> {
+    fn new(iter: I, toc: Option<&'b mut TocBuilder>, ids: &'ids mut IdMap) -> Self {
         HeadingLinks {
             inner: iter,
             toc,
             buf: VecDeque::new(),
+            id_map: ids,
         }
     }
 }
 
-impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, 'b, I> {
+impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, 'b, 'ids, I> {
     type Item = Event<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -301,7 +325,7 @@ fn next(&mut self) -> Option<Self::Item> {
                 }
                 self.buf.push_back(event);
             }
-            let id = derive_id(id);
+            let id = self.id_map.derive(id);
 
             if let Some(ref mut builder) = self.toc {
                 let mut html_header = String::new();
@@ -467,10 +491,17 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 }
 
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
-                          sess: Option<&session::Session>) {
-    tests.set_position(position);
+pub struct TestableCodeError(());
 
+impl fmt::Display for TestableCodeError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "invalid start of a new code block")
+    }
+}
+
+pub fn find_testable_code(
+    doc: &str, tests: &mut test::Collector, error_codes: ErrorCodes,
+) -> Result<(), TestableCodeError> {
     let mut parser = Parser::new(doc);
     let mut prev_offset = 0;
     let mut nb_lines = 0;
@@ -481,7 +512,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                 let block_info = if s.is_empty() {
                     LangString::all_false()
                 } else {
-                    LangString::parse(&*s)
+                    LangString::parse(&*s, error_codes)
                 };
                 if !block_info.rust {
                     continue
@@ -510,18 +541,10 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                     let text = lines.collect::<Vec<Cow<str>>>().join("\n");
                     nb_lines += doc[prev_offset..offset].lines().count();
                     let line = tests.get_line() + (nb_lines - 1);
-                    let filename = tests.get_filename();
-                    tests.add_test(text.to_owned(),
-                                   block_info.should_panic, block_info.no_run,
-                                   block_info.ignore, block_info.test_harness,
-                                   block_info.compile_fail, block_info.error_codes,
-                                   line, filename, block_info.allow_fail);
+                    tests.add_test(text, block_info, line);
                     prev_offset = offset;
                 } else {
-                    if let Some(ref sess) = sess {
-                        sess.span_warn(position, "invalid start of a new code block");
-                    }
-                    break;
+                    return Err(TestableCodeError(()));
                 }
             }
             Event::Start(Tag::Header(level)) => {
@@ -539,19 +562,20 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
             _ => {}
         }
     }
+    Ok(())
 }
 
 #[derive(Eq, PartialEq, Clone, Debug)]
-struct LangString {
+pub struct LangString {
     original: String,
-    should_panic: bool,
-    no_run: bool,
-    ignore: bool,
-    rust: bool,
-    test_harness: bool,
-    compile_fail: bool,
-    error_codes: Vec<String>,
-    allow_fail: bool,
+    pub should_panic: bool,
+    pub no_run: bool,
+    pub ignore: bool,
+    pub rust: bool,
+    pub test_harness: bool,
+    pub compile_fail: bool,
+    pub error_codes: Vec<String>,
+    pub allow_fail: bool,
 }
 
 impl LangString {
@@ -569,14 +593,11 @@ fn all_false() -> LangString {
         }
     }
 
-    fn parse(string: &str) -> LangString {
+    fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString {
+        let allow_error_code_check = allow_error_code_check.as_bool();
         let mut seen_rust_tags = false;
         let mut seen_other_tags = false;
         let mut data = LangString::all_false();
-        let mut allow_error_code_check = false;
-        if UnstableFeatures::from_environment().is_nightly_build() {
-            allow_error_code_check = true;
-        }
 
         data.original = string.to_owned();
         let tokens = string.split(|c: char|
@@ -623,7 +644,8 @@ fn parse(string: &str) -> LangString {
 
 impl<'a> fmt::Display for Markdown<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let Markdown(md, links) = *self;
+        let Markdown(md, links, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
@@ -643,12 +665,11 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        html::push_html(&mut s,
-                        Footnotes::new(
-                            CodeBlocks::new(
-                                LinkReplacer::new(
-                                    HeadingLinks::new(p, None),
-                                    links))));
+        let p = HeadingLinks::new(p, None, &mut ids);
+        let p = LinkReplacer::new(p, links);
+        let p = CodeBlocks::new(p, codes);
+        let p = Footnotes::new(p);
+        html::push_html(&mut s, p);
 
         fmt.write_str(&s)
     }
@@ -656,7 +677,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
 impl<'a> fmt::Display for MarkdownWithToc<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownWithToc(md) = *self;
+        let MarkdownWithToc(md, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         let mut opts = Options::empty();
         opts.insert(OPTION_ENABLE_TABLES);
@@ -668,8 +690,12 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
         let mut toc = TocBuilder::new();
 
-        html::push_html(&mut s,
-                        Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, Some(&mut toc)))));
+        {
+            let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
+            let p = CodeBlocks::new(p, codes);
+            let p = Footnotes::new(p);
+            html::push_html(&mut s, p);
+        }
 
         write!(fmt, "<nav id=\"TOC\">{}</nav>", toc.into_toc())?;
 
@@ -679,7 +705,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
 impl<'a> fmt::Display for MarkdownHtml<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownHtml(md) = *self;
+        let MarkdownHtml(md, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
@@ -697,8 +724,10 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        html::push_html(&mut s,
-                        Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None))));
+        let p = HeadingLinks::new(p, None, &mut ids);
+        let p = CodeBlocks::new(p, codes);
+        let p = Footnotes::new(p);
+        html::push_html(&mut s, p);
 
         fmt.write_str(&s)
     }
@@ -812,7 +841,10 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
         let p = Parser::new_with_broken_link_callback(md, opts,
             Some(&push));
 
-        let iter = Footnotes::new(HeadingLinks::new(p, None));
+        // There's no need to thread an IdMap through to here because
+        // the IDs generated aren't going to be emitted anywhere.
+        let mut ids = IdMap::new();
+        let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
 
         for ev in iter {
             if let Event::Start(Tag::Link(dest, _)) = ev {
@@ -831,18 +863,74 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
     links
 }
 
+#[derive(Default)]
+pub struct IdMap {
+    map: HashMap<String, usize>,
+}
+
+impl IdMap {
+    pub fn new() -> Self {
+        IdMap::default()
+    }
+
+    pub fn populate<I: IntoIterator<Item=String>>(&mut self, ids: I) {
+        for id in ids {
+            let _ = self.derive(id);
+        }
+    }
+
+    pub fn reset(&mut self) {
+        self.map = HashMap::new();
+    }
+
+    pub fn derive(&mut self, candidate: String) -> String {
+        let id = match self.map.get_mut(&candidate) {
+            None => candidate,
+            Some(a) => {
+                let id = format!("{}-{}", candidate, *a);
+                *a += 1;
+                id
+            }
+        };
+
+        self.map.insert(id.clone(), 1);
+        id
+    }
+}
+
+#[cfg(test)]
+#[test]
+fn test_unique_id() {
+    let input = ["foo", "examples", "examples", "method.into_iter","examples",
+                 "method.into_iter", "foo", "main", "search", "methods",
+                 "examples", "method.into_iter", "assoc_type.Item", "assoc_type.Item"];
+    let expected = ["foo", "examples", "examples-1", "method.into_iter", "examples-2",
+                    "method.into_iter-1", "foo-1", "main", "search", "methods",
+                    "examples-3", "method.into_iter-2", "assoc_type.Item", "assoc_type.Item-1"];
+
+    let map = RefCell::new(IdMap::new());
+    let test = || {
+        let mut map = map.borrow_mut();
+        let actual: Vec<String> = input.iter().map(|s| map.derive(s.to_string())).collect();
+        assert_eq!(&actual[..], expected);
+    };
+    test();
+    map.borrow_mut().reset();
+    test();
+}
+
 #[cfg(test)]
 mod tests {
-    use super::{LangString, Markdown, MarkdownHtml};
+    use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
     use super::plain_summary_line;
-    use html::render::reset_ids;
+    use std::cell::RefCell;
 
     #[test]
     fn test_lang_string_parse() {
         fn t(s: &str,
             should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
             compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) {
-            assert_eq!(LangString::parse(s), LangString {
+            assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
                 should_panic,
                 no_run,
                 ignore,
@@ -878,19 +966,12 @@ fn v() -> Vec<String> {
         t("text,no_run",           false,        true,   false,  false, false, false, false, v());
     }
 
-    #[test]
-    fn issue_17736() {
-        let markdown = "# title";
-        Markdown(markdown, &[]).to_string();
-        reset_ids(true);
-    }
-
     #[test]
     fn test_header() {
         fn t(input: &str, expect: &str) {
-            let output = Markdown(input, &[]).to_string();
+            let mut map = IdMap::new();
+            let output = Markdown(input, &[], RefCell::new(&mut map), ErrorCodes::Yes).to_string();
             assert_eq!(output, expect, "original: {}", input);
-            reset_ids(true);
         }
 
         t("# Foo bar", "<h1 id=\"foo-bar\" class=\"section-header\">\
@@ -909,28 +990,24 @@ fn t(input: &str, expect: &str) {
 
     #[test]
     fn test_header_ids_multiple_blocks() {
-        fn t(input: &str, expect: &str) {
-            let output = Markdown(input, &[]).to_string();
+        let mut map = IdMap::new();
+        fn t(map: &mut IdMap, input: &str, expect: &str) {
+            let output = Markdown(input, &[], RefCell::new(map), ErrorCodes::Yes).to_string();
             assert_eq!(output, expect, "original: {}", input);
         }
 
-        let test = || {
-            t("# Example", "<h1 id=\"example\" class=\"section-header\">\
-              <a href=\"#example\">Example</a></h1>");
-            t("# Panics", "<h1 id=\"panics\" class=\"section-header\">\
-              <a href=\"#panics\">Panics</a></h1>");
-            t("# Example", "<h1 id=\"example-1\" class=\"section-header\">\
-              <a href=\"#example-1\">Example</a></h1>");
-            t("# Main", "<h1 id=\"main-1\" class=\"section-header\">\
-              <a href=\"#main-1\">Main</a></h1>");
-            t("# Example", "<h1 id=\"example-2\" class=\"section-header\">\
-              <a href=\"#example-2\">Example</a></h1>");
-            t("# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\
-              <a href=\"#panics-1\">Panics</a></h1>");
-        };
-        test();
-        reset_ids(true);
-        test();
+        t(&mut map, "# Example", "<h1 id=\"example\" class=\"section-header\">\
+            <a href=\"#example\">Example</a></h1>");
+        t(&mut map, "# Panics", "<h1 id=\"panics\" class=\"section-header\">\
+            <a href=\"#panics\">Panics</a></h1>");
+        t(&mut map, "# Example", "<h1 id=\"example-1\" class=\"section-header\">\
+            <a href=\"#example-1\">Example</a></h1>");
+        t(&mut map, "# Main", "<h1 id=\"main\" class=\"section-header\">\
+            <a href=\"#main\">Main</a></h1>");
+        t(&mut map, "# Example", "<h1 id=\"example-2\" class=\"section-header\">\
+            <a href=\"#example-2\">Example</a></h1>");
+        t(&mut map, "# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\
+            <a href=\"#panics-1\">Panics</a></h1>");
     }
 
     #[test]
@@ -951,7 +1028,8 @@ fn t(input: &str, expect: &str) {
     #[test]
     fn test_markdown_html_escape() {
         fn t(input: &str, expect: &str) {
-            let output = MarkdownHtml(input).to_string();
+            let mut idmap = IdMap::new();
+            let output = MarkdownHtml(input, RefCell::new(&mut idmap), ErrorCodes::Yes).to_string();
             assert_eq!(output, expect, "original: {}", input);
         }
 
index 24a9bf416e44420f101972a7c7cd52dee65b3180..c2978a62489a0d86bd787212f9abc144d2d4dc81 100644 (file)
 use std::path::{PathBuf, Path, Component};
 use std::str;
 use std::sync::Arc;
+use std::rc::Rc;
 
 use externalfiles::ExternalHtml;
 
 use serialize::json::{ToJson, Json, as_json};
 use syntax::ast;
 use syntax::codemap::FileName;
+use syntax::feature_gate::UnstableFeatures;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
@@ -72,7 +74,7 @@
 use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
 use html::format::fmt_impl_for_trait_page;
 use html::item_type::ItemType;
-use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine};
+use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap};
 use html::{highlight, layout};
 
 use minifier;
@@ -88,7 +90,7 @@
 /// easily cloned because it is cloned per work-job (about once per item in the
 /// rustdoc tree).
 #[derive(Clone)]
-pub struct Context {
+struct Context {
     /// Current hierarchy of components leading down to what's currently being
     /// rendered
     pub current: Vec<String>,
@@ -99,10 +101,13 @@ pub struct Context {
     /// real location of an item. This is used to allow external links to
     /// publicly reused items to redirect to the right location.
     pub render_redirect_pages: bool,
+    pub codes: ErrorCodes,
+    /// The map used to ensure all generated 'id=' attributes are unique.
+    id_map: Rc<RefCell<IdMap>>,
     pub shared: Arc<SharedContext>,
 }
 
-pub struct SharedContext {
+struct SharedContext {
     /// The path to the crate root source minus the file name.
     /// Used for simplifying paths to the highlighted source code files.
     pub src_root: PathBuf,
@@ -450,9 +455,8 @@ fn to_json(&self) -> Json {
 
 thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 thread_local!(pub static CURRENT_LOCATION_KEY: RefCell<Vec<String>> = RefCell::new(Vec::new()));
-thread_local!(pub static USED_ID_MAP: RefCell<FxHashMap<String, usize>> = RefCell::new(init_ids()));
 
-fn init_ids() -> FxHashMap<String, usize> {
+pub fn initial_ids() -> Vec<String> {
     [
      "main",
      "search",
@@ -470,36 +474,7 @@ fn init_ids() -> FxHashMap<String, usize> {
      "methods",
      "deref-methods",
      "implementations",
-    ].into_iter().map(|id| (String::from(*id), 1)).collect()
-}
-
-/// This method resets the local table of used ID attributes. This is typically
-/// used at the beginning of rendering an entire HTML page to reset from the
-/// previous state (if any).
-pub fn reset_ids(embedded: bool) {
-    USED_ID_MAP.with(|s| {
-        *s.borrow_mut() = if embedded {
-            init_ids()
-        } else {
-            FxHashMap()
-        };
-    });
-}
-
-pub fn derive_id(candidate: String) -> String {
-    USED_ID_MAP.with(|map| {
-        let id = match map.borrow_mut().get_mut(&candidate) {
-            None => candidate,
-            Some(a) => {
-                let id = format!("{}-{}", candidate, *a);
-                *a += 1;
-                id
-            }
-        };
-
-        map.borrow_mut().insert(id.clone(), 1);
-        id
-    })
+    ].into_iter().map(|id| (String::from(*id))).collect()
 }
 
 /// Generates the documentation for `crate` into the directory `dst`
@@ -513,7 +488,8 @@ pub fn run(mut krate: clean::Crate,
            renderinfo: RenderInfo,
            sort_modules_alphabetically: bool,
            themes: Vec<PathBuf>,
-           enable_minification: bool) -> Result<(), Error> {
+           enable_minification: bool,
+           id_map: IdMap) -> Result<(), Error> {
     let src_root = match krate.src {
         FileName::Real(ref p) => match p.parent() {
             Some(p) => p.to_path_buf(),
@@ -581,6 +557,8 @@ pub fn run(mut krate: clean::Crate,
         current: Vec::new(),
         dst,
         render_redirect_pages: false,
+        codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
+        id_map: Rc::new(RefCell::new(id_map)),
         shared: Arc::new(scx),
     };
 
@@ -1708,6 +1686,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl Context {
+    fn derive_id(&self, id: String) -> String {
+        let mut map = self.id_map.borrow_mut();
+        map.derive(id)
+    }
+
     /// String representation of how to get back to the root path of the 'doc/'
     /// folder in terms of a relative URL.
     fn root_path(&self) -> String {
@@ -1862,7 +1845,10 @@ fn render_item(&self,
             resource_suffix: &self.shared.resource_suffix,
         };
 
-        reset_ids(true);
+        {
+            self.id_map.borrow_mut().reset();
+            self.id_map.borrow_mut().populate(initial_ids());
+        }
 
         if !self.render_redirect_pages {
             layout::render(writer, &self.shared.layout, &page,
@@ -2219,14 +2205,17 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
 
 /// Render md_text as markdown.
 fn render_markdown(w: &mut fmt::Formatter,
+                   cx: &Context,
                    md_text: &str,
                    links: Vec<(String, String)>,
-                   prefix: &str,)
+                   prefix: &str)
                    -> fmt::Result {
-    write!(w, "<div class='docblock'>{}{}</div>", prefix, Markdown(md_text, &links))
+    let mut ids = cx.id_map.borrow_mut();
+    write!(w, "<div class='docblock'>{}{}</div>",
+        prefix, Markdown(md_text, &links, RefCell::new(&mut ids), cx.codes))
 }
 
-fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink,
+fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink,
                   prefix: &str) -> fmt::Result {
     if let Some(s) = item.doc_value() {
         let markdown = if s.contains('\n') {
@@ -2235,7 +2224,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
         } else {
             plain_summary_line(Some(s)).to_string()
         };
-        render_markdown(w, &markdown, item.links(), prefix)?;
+        render_markdown(w, cx, &markdown, item.links(), prefix)?;
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock'>{}</div>", prefix)?;
     }
@@ -2250,7 +2239,6 @@ fn render_assoc_const_value(item: &clean::Item) -> String {
                 None,
                 None,
                 None,
-                None,
             )
         }
         _ => String::new(),
@@ -2261,7 +2249,7 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
                  cx: &Context, prefix: &str) -> fmt::Result {
     if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
         debug!("Doc block: =====\n{}\n=====", s);
-        render_markdown(w, &*s, item.links(), prefix)?;
+        render_markdown(w, cx, &*s, item.links(), prefix)?;
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock'>{}</div>", prefix)?;
     }
@@ -2427,7 +2415,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
             let (short, name) = item_ty_to_strs(&myty.unwrap());
             write!(w, "<h2 id='{id}' class='section-header'>\
                        <a href=\"#{id}\">{name}</a></h2>\n<table>",
-                   id = derive_id(short.to_owned()), name = name)?;
+                   id = cx.derive_id(short.to_owned()), name = name)?;
         }
 
         match myitem.inner {
@@ -2508,6 +2496,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
 
 fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<String> {
     let mut stability = vec![];
+    let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
 
     if let Some(stab) = item.stability.as_ref() {
         let deprecated_reason = if show_reason && !stab.deprecated_reason.is_empty() {
@@ -2521,14 +2510,12 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
             } else {
                 String::new()
             };
+            let mut ids = cx.id_map.borrow_mut();
+            let html = MarkdownHtml(&deprecated_reason, RefCell::new(&mut ids), error_codes);
             let text = if stability::deprecation_in_effect(&stab.deprecated_since) {
-                format!("Deprecated{}{}",
-                        since,
-                        MarkdownHtml(&deprecated_reason))
+                format!("Deprecated{}{}", since, html)
             } else {
-                format!("Deprecating in {}{}",
-                        Escape(&stab.deprecated_since),
-                        MarkdownHtml(&deprecated_reason))
+                format!("Deprecating in {}{}", Escape(&stab.deprecated_since), html)
             };
             stability.push(format!("<div class='stab deprecated'>{}</div>", text))
         };
@@ -2555,11 +2542,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
                                             </div>",
                                            unstable_extra));
                 } else {
+                    let mut ids = cx.id_map.borrow_mut();
                     let text = format!("<summary><span class=microscope>🔬</span> \
                                         This is a nightly-only experimental API. {}\
                                         </summary>{}",
                                        unstable_extra,
-                                       MarkdownHtml(&stab.unstable_reason));
+                                       MarkdownHtml(
+                                           &stab.unstable_reason,
+                                           RefCell::new(&mut ids),
+                                           error_codes));
                     stability.push(format!("<div class='stab unstable'><details>{}</details></div>",
                                    text));
                 }
@@ -2579,14 +2570,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
             String::new()
         };
 
+        let mut ids = cx.id_map.borrow_mut();
         let text = if stability::deprecation_in_effect(&depr.since) {
             format!("Deprecated{}{}",
                     since,
-                    MarkdownHtml(&note))
+                    MarkdownHtml(&note, RefCell::new(&mut ids), error_codes))
         } else {
             format!("Deprecating in {}{}",
                     Escape(&depr.since),
-                    MarkdownHtml(&note))
+                    MarkdownHtml(&note, RefCell::new(&mut ids), error_codes))
         };
         stability.push(format!("<div class='stab deprecated'>{}</div>", text))
     }
@@ -2827,8 +2819,8 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
                   -> fmt::Result {
         let name = m.name.as_ref().unwrap();
         let item_type = m.type_();
-        let id = derive_id(format!("{}.{}", item_type, name));
-        let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+        let id = cx.derive_id(format!("{}.{}", item_type, name));
+        let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
         write!(w, "{extra}<h3 id='{id}' class='method'>\
                    <span id='{ns_id}' class='invisible'><code>",
                extra = render_spotlight_traits(m)?,
@@ -3183,10 +3175,10 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                        document_non_exhaustive_header(it))?;
             document_non_exhaustive(w, it)?;
             for (field, ty) in fields {
-                let id = derive_id(format!("{}.{}",
+                let id = cx.derive_id(format!("{}.{}",
                                            ItemType::StructField,
                                            field.name.as_ref().unwrap()));
-                let ns_id = derive_id(format!("{}.{}",
+                let ns_id = cx.derive_id(format!("{}.{}",
                                               field.name.as_ref().unwrap(),
                                               ItemType::StructField.name_space()));
                 write!(w, "<span id=\"{id}\" class=\"{item_type} small-section-header\">
@@ -3317,10 +3309,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                    document_non_exhaustive_header(it))?;
         document_non_exhaustive(w, it)?;
         for variant in &e.variants {
-            let id = derive_id(format!("{}.{}",
+            let id = cx.derive_id(format!("{}.{}",
                                        ItemType::Variant,
                                        variant.name.as_ref().unwrap()));
-            let ns_id = derive_id(format!("{}.{}",
+            let ns_id = cx.derive_id(format!("{}.{}",
                                           variant.name.as_ref().unwrap(),
                                           ItemType::Variant.name_space()));
             write!(w, "<span id=\"{id}\" class=\"variant small-section-header\">\
@@ -3348,7 +3340,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
             if let clean::VariantItem(Variant {
                 kind: VariantKind::Struct(ref s)
             }) = variant.inner {
-                let variant_id = derive_id(format!("{}.{}.fields",
+                let variant_id = cx.derive_id(format!("{}.{}.fields",
                                                    ItemType::Variant,
                                                    variant.name.as_ref().unwrap()));
                 write!(w, "<span class='docblock autohide sub-variant' id='{id}'>",
@@ -3358,10 +3350,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                 for field in &s.fields {
                     use clean::StructFieldItem;
                     if let StructFieldItem(ref ty) = field.inner {
-                        let id = derive_id(format!("variant.{}.field.{}",
+                        let id = cx.derive_id(format!("variant.{}.field.{}",
                                                    variant.name.as_ref().unwrap(),
                                                    field.name.as_ref().unwrap()));
-                        let ns_id = derive_id(format!("{}.{}.{}.{}",
+                        let ns_id = cx.derive_id(format!("{}.{}.{}.{}",
                                                       variant.name.as_ref().unwrap(),
                                                       ItemType::Variant.name_space(),
                                                       field.name.as_ref().unwrap(),
@@ -3790,7 +3782,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
                render_mode: RenderMode, outer_version: Option<&str>,
                show_def_docs: bool) -> fmt::Result {
     if render_mode == RenderMode::Normal {
-        let id = derive_id(match i.inner_impl().trait_ {
+        let id = cx.derive_id(match i.inner_impl().trait_ {
             Some(ref t) => format!("impl-{}", small_url_encode(&format!("{:#}", t))),
             None => "impl".to_string(),
         });
@@ -3810,8 +3802,9 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
         }
         write!(w, "</span></td></tr></tbody></table></h3>")?;
         if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
+            let mut ids = cx.id_map.borrow_mut();
             write!(w, "<div class='docblock'>{}</div>",
-                   Markdown(&*dox, &i.impl_item.links()))?;
+                   Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?;
         }
     }
 
@@ -3832,8 +3825,8 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             clean::TyMethodItem(clean::TyMethod{ ref decl, .. }) => {
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
-                    let id = derive_id(format!("{}.{}", item_type, name));
-                    let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+                    let id = cx.derive_id(format!("{}.{}", item_type, name));
+                    let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                     write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
                     write!(w, "{}", spotlight_decl(decl)?)?;
                     write!(w, "<span id='{}' class='invisible'>", ns_id)?;
@@ -3854,24 +3847,24 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
                 }
             }
             clean::TypedefItem(ref tydef, _) => {
-                let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name));
-                let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+                let id = cx.derive_id(format!("{}.{}", ItemType::AssociatedType, name));
+                let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                 write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
                 write!(w, "</code></span></h4>\n")?;
             }
             clean::AssociatedConstItem(ref ty, ref default) => {
-                let id = derive_id(format!("{}.{}", item_type, name));
-                let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+                let id = cx.derive_id(format!("{}.{}", item_type, name));
+                let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                 write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
                 write!(w, "</code></span></h4>\n")?;
             }
             clean::AssociatedTypeItem(ref bounds, ref default) => {
-                let id = derive_id(format!("{}.{}", item_type, name));
-                let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+                let id = cx.derive_id(format!("{}.{}", item_type, name));
+                let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                 write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
@@ -3897,7 +3890,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
                         } else if show_def_docs {
                             // In case the item isn't documented,
                             // provide short documentation from the trait.
-                            document_short(w, it, link, &prefix)?;
+                            document_short(w, cx, it, link, &prefix)?;
                         }
                     }
                 } else {
@@ -3909,7 +3902,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             } else {
                 document_stability(w, cx, item)?;
                 if show_def_docs {
-                    document_short(w, item, link, &prefix)?;
+                    document_short(w, cx, item, link, &prefix)?;
                 }
             }
         }
@@ -4557,7 +4550,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         }
         write!(fmt, "</pre>")?;
         write!(fmt, "{}",
-               highlight::render_with_highlighting(s, None, None, None, None))?;
+               highlight::render_with_highlighting(s, None, None, None))?;
         Ok(())
     }
 }
@@ -4568,7 +4561,6 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         w.write_str(&highlight::render_with_highlighting(&t.source,
                                                          Some("macro"),
                                                          None,
-                                                         None,
                                                          None))
     })?;
     document(w, cx, it)
@@ -4715,25 +4707,6 @@ pub fn cache() -> Arc<Cache> {
     CACHE_KEY.with(|c| c.borrow().clone())
 }
 
-#[cfg(test)]
-#[test]
-fn test_unique_id() {
-    let input = ["foo", "examples", "examples", "method.into_iter","examples",
-                 "method.into_iter", "foo", "main", "search", "methods",
-                 "examples", "method.into_iter", "assoc_type.Item", "assoc_type.Item"];
-    let expected = ["foo", "examples", "examples-1", "method.into_iter", "examples-2",
-                    "method.into_iter-1", "foo-1", "main-1", "search-1", "methods-1",
-                    "examples-3", "method.into_iter-2", "assoc_type.Item", "assoc_type.Item-1"];
-
-    let test = || {
-        let actual: Vec<String> = input.iter().map(|s| derive_id(s.to_string())).collect();
-        assert_eq!(&actual[..], expected);
-    };
-    test();
-    reset_ids(true);
-    test();
-}
-
 #[cfg(test)]
 #[test]
 fn test_name_key() {
index b689e2fa3854e3608f2344b8f8ebd7ab4e745891..496029e33fc65cebf2541ec3155aa68b1a788d5a 100644 (file)
@@ -610,11 +610,16 @@ a {
 
 .content .search-results td:first-child {
        padding-right: 0;
-       width: 75%;
+       width: 50%;
 }
 .content .search-results td:first-child a {
        padding-right: 10px;
 }
+.content .search-results td:first-child a:after {
+    clear: both;
+    content: "";
+    display: block;
+}
 .content .search-results td:first-child a span {
        float: left;
 }
index b4342f4749185cd84eaa85796b15968f5b2fb020..faca264ea1006c47467f224a07053e13457748af 100644 (file)
@@ -33,7 +33,7 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t
        background: rgba(0, 0, 0, 0);
 }
 
-.docblock p > code, .docblock-short p > code {
+.docblock code, .docblock-short code {
        background-color: #2A2A2A;
 }
 pre {
index e84e3cb56636e485048b3be7d856e3225f47e891..5725a41d939d55947b321e74944e04fa7abb72d0 100644 (file)
@@ -35,7 +35,7 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t
        background: rgba(0, 0, 0, 0);
 }
 
-.docblock p > code, .docblock-short p > code {
+.docblock code, .docblock-short code {
        background-color: #F5F5F5;
 }
 pre {
index 041a233617083e4c0ef7c53990a3174c52a407ed..bd7f7386fd14b6aa7ce56898ee182dd592460d81 100644 (file)
@@ -26,6 +26,7 @@
 #![feature(entry_and_modify)]
 #![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
+#![feature(const_fn)]
 
 #![recursion_limit="256"]
 
@@ -96,8 +97,6 @@ pub mod html {
 mod test;
 mod theme;
 
-use clean::AttributesExt;
-
 struct Output {
     krate: clean::Crate,
     renderinfo: html::render::RenderInfo,
@@ -290,7 +289,7 @@ fn opts() -> Vec<RustcOptGroup> {
                      "edition to use when compiling rust code (default: 2015)",
                      "EDITION")
         }),
-        unstable("color", |o| {
+        stable("color", |o| {
             o.optopt("",
                      "color",
                      "Configure coloring of output:
@@ -299,7 +298,7 @@ fn opts() -> Vec<RustcOptGroup> {
                                           never  = never colorize output",
                      "auto|always|never")
         }),
-        unstable("error-format", |o| {
+        stable("error-format", |o| {
             o.optopt("",
                      "error-format",
                      "How errors and other messages are produced",
@@ -367,8 +366,8 @@ fn main_args(args: &[String]) -> isize {
 
     if matches.opt_strs("passes") == ["list"] {
         println!("Available passes for running rustdoc:");
-        for &(name, _, description) in passes::PASSES {
-            println!("{:>20} - {}", name, description);
+        for pass in passes::PASSES {
+            println!("{:>20} - {}", pass.name(), pass.description());
         }
         println!("\nDefault passes for rustdoc:");
         for &name in passes::DEFAULT_PASSES {
@@ -500,12 +499,14 @@ fn main_args(args: &[String]) -> isize {
         }
     }
 
+    let mut id_map = html::markdown::IdMap::new();
+    id_map.populate(html::render::initial_ids());
     let external_html = match ExternalHtml::load(
             &matches.opt_strs("html-in-header"),
             &matches.opt_strs("html-before-content"),
             &matches.opt_strs("html-after-content"),
             &matches.opt_strs("markdown-before-content"),
-            &matches.opt_strs("markdown-after-content"), &diag) {
+            &matches.opt_strs("markdown-after-content"), &diag, &mut id_map) {
         Some(eh) => eh,
         None => return 3,
     };
@@ -562,7 +563,7 @@ fn main_args(args: &[String]) -> isize {
                                   renderinfo,
                                   sort_modules_alphabetically,
                                   themes,
-                                  enable_minification)
+                                  enable_minification, id_map)
                     .expect("failed to generate documentation");
                 0
             }
@@ -628,7 +629,7 @@ fn rust_input<R, F>(cratefile: PathBuf,
 where R: 'static + Send,
       F: 'static + Send + FnOnce(Output) -> R
 {
-    let mut default_passes = if matches.opt_present("no-defaults") {
+    let default_passes = if matches.opt_present("no-defaults") {
         passes::DefaultPassOption::None
     } else if matches.opt_present("document-private-items") {
         passes::DefaultPassOption::Private
@@ -636,8 +637,8 @@ fn rust_input<R, F>(cratefile: PathBuf,
         passes::DefaultPassOption::Default
     };
 
-    let mut manual_passes = matches.opt_strs("passes");
-    let mut plugins = matches.opt_strs("plugins");
+    let manual_passes = matches.opt_strs("passes");
+    let plugins = matches.opt_strs("plugins");
 
     // First, parse the crate and extract all relevant information.
     let mut paths = SearchPaths::new();
@@ -671,11 +672,11 @@ fn rust_input<R, F>(cratefile: PathBuf,
     let result = rustc_driver::monitor(move || syntax::with_globals(move || {
         use rustc::session::config::Input;
 
-        let (mut krate, renderinfo) =
+        let (mut krate, renderinfo, passes) =
             core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
                            display_warnings, crate_name.clone(),
                            force_unstable_if_unmarked, edition, cg, error_format,
-                           lint_opts, lint_cap, describe_lints);
+                           lint_opts, lint_cap, describe_lints, manual_passes, default_passes);
 
         info!("finished with rustc");
 
@@ -685,58 +686,6 @@ fn rust_input<R, F>(cratefile: PathBuf,
 
         krate.version = crate_version;
 
-        let diag = core::new_handler(error_format, None);
-
-        fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
-            let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \
-                                                     considered deprecated", name));
-            msg.warn("please see https://github.com/rust-lang/rust/issues/44136");
-
-            if name == "no_default_passes" {
-                msg.help("you may want to use `#![doc(document_private_items)]`");
-            }
-
-            msg.emit();
-        }
-
-        // Process all of the crate attributes, extracting plugin metadata along
-        // with the passes which we are supposed to run.
-        for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
-            let name = attr.name().map(|s| s.as_str());
-            let name = name.as_ref().map(|s| &s[..]);
-            if attr.is_word() {
-                if name == Some("no_default_passes") {
-                    report_deprecated_attr("no_default_passes", &diag);
-                    if default_passes == passes::DefaultPassOption::Default {
-                        default_passes = passes::DefaultPassOption::None;
-                    }
-                }
-            } else if let Some(value) = attr.value_str() {
-                let sink = match name {
-                    Some("passes") => {
-                        report_deprecated_attr("passes = \"...\"", &diag);
-                        &mut manual_passes
-                    },
-                    Some("plugins") => {
-                        report_deprecated_attr("plugins = \"...\"", &diag);
-                        &mut plugins
-                    },
-                    _ => continue,
-                };
-                sink.extend(value.as_str().split_whitespace().map(|p| p.to_string()));
-            }
-
-            if attr.is_word() && name == Some("document_private_items") {
-                if default_passes == passes::DefaultPassOption::Default {
-                    default_passes = passes::DefaultPassOption::Private;
-                }
-            }
-        }
-
-        let mut passes: Vec<String> =
-            passes::defaults(default_passes).iter().map(|p| p.to_string()).collect();
-        passes.extend(manual_passes);
-
         if !plugins.is_empty() {
             eprintln!("WARNING: --plugins no longer functions; see CVE-2018-1000622");
         }
@@ -749,8 +698,13 @@ fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
 
         for pass in &passes {
             // determine if we know about this pass
-            let pass = match passes::PASSES.iter().find(|(p, ..)| p == pass) {
-                Some(pass) => pass.1,
+            let pass = match passes::find_pass(pass) {
+                Some(pass) => if let Some(pass) = pass.late_fn() {
+                    pass
+                } else {
+                    // not a late pass, but still valid so don't report the error
+                    continue
+                }
                 None => {
                     error!("unknown pass {}, skipping", *pass);
 
index 36a8fc94dba2f377cbc5daa903dc86c33f4daa5d..05661dc6856637f0c97410136318d2e60e26da26 100644 (file)
@@ -12,6 +12,7 @@
 use std::fs::File;
 use std::io::prelude::*;
 use std::path::{PathBuf, Path};
+use std::cell::RefCell;
 
 use errors;
 use getopts;
 use rustc::session::search_paths::SearchPaths;
 use rustc::session::config::{Externs, CodegenOptions};
 use syntax::codemap::DUMMY_SP;
+use syntax::feature_gate::UnstableFeatures;
 use syntax::edition::Edition;
 
 use externalfiles::{ExternalHtml, LoadStringError, load_string};
 
-use html::render::reset_ids;
 use html::escape::Escape;
 use html::markdown;
-use html::markdown::{Markdown, MarkdownWithToc, find_testable_code};
+use html::markdown::{ErrorCodes, IdMap, Markdown, MarkdownWithToc, find_testable_code};
 use test::{TestOptions, Collector};
 
 /// Separate any lines at the start of the file that begin with `# ` or `%`.
@@ -86,12 +87,12 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches,
     }
     let title = metadata[0];
 
-    reset_ids(false);
-
+    let mut ids = IdMap::new();
+    let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
     let text = if include_toc {
-        MarkdownWithToc(text).to_string()
+        MarkdownWithToc(text, RefCell::new(&mut ids), error_codes).to_string()
     } else {
-        Markdown(text, &[]).to_string()
+        Markdown(text, &[], RefCell::new(&mut ids), error_codes).to_string()
     };
 
     let err = write!(
@@ -156,7 +157,12 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(PathBuf::from(input)),
                                        linker, edition);
-    find_testable_code(&input_str, &mut collector, DUMMY_SP, None);
+    collector.set_position(DUMMY_SP);
+    let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
+    let res = find_testable_code(&input_str, &mut collector, codes);
+    if let Err(err) = res {
+        diag.span_warn(DUMMY_SP, &err.to_string());
+    }
     test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&test_args, collector.tests,
                        testing::Options::new().display_output(display_warnings));
index 6f70fcf1099e634dbecc643b5b14c8e756db6487..33d052775ba76d3af28bdbe16769878dc83b27c9 100644 (file)
 use clean::{self, DocFragment, Item};
 use fold;
 use fold::DocFolder;
+use passes::Pass;
 use std::mem::replace;
 
+pub const COLLAPSE_DOCS: Pass =
+    Pass::late("collapse-docs", collapse_docs,
+        "concatenates all document attributes into one document attribute");
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum DocFragmentKind {
     Sugared,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
new file mode 100644 (file)
index 0000000..28d504c
--- /dev/null
@@ -0,0 +1,597 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use clean::*;
+
+use rustc::lint as lint;
+use rustc::hir;
+use rustc::hir::def::Def;
+use rustc::ty;
+use syntax;
+use syntax::ast::{self, Ident, NodeId};
+use syntax::feature_gate::UnstableFeatures;
+use syntax::symbol::Symbol;
+use syntax_pos::{self, DUMMY_SP};
+
+use std::ops::Range;
+
+use core::DocContext;
+use fold::DocFolder;
+use html::markdown::markdown_links;
+use passes::Pass;
+
+pub const COLLECT_INTRA_DOC_LINKS: Pass =
+    Pass::early("collect-intra-doc-links", collect_intra_doc_links,
+                "reads a crate's documentation to resolve intra-doc-links");
+
+pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext) -> Crate {
+    if !UnstableFeatures::from_environment().is_nightly_build() {
+        krate
+    } else {
+        let mut coll = LinkCollector::new(cx);
+
+        coll.fold_crate(krate)
+    }
+}
+
+#[derive(Debug)]
+enum PathKind {
+    /// can be either value or type, not a macro
+    Unknown,
+    /// macro
+    Macro,
+    /// values, functions, consts, statics, everything in the value namespace
+    Value,
+    /// types, traits, everything in the type namespace
+    Type,
+}
+
+struct LinkCollector<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
+    cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>,
+    mod_ids: Vec<NodeId>,
+}
+
+impl<'a, 'tcx, 'rcx, 'cstore> LinkCollector<'a, 'tcx, 'rcx, 'cstore> {
+    fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
+        LinkCollector {
+            cx,
+            mod_ids: Vec::new(),
+        }
+    }
+
+    /// Resolve a given string as a path, along with whether or not it is
+    /// in the value namespace. Also returns an optional URL fragment in the case
+    /// of variants and methods
+    fn resolve(&self, path_str: &str, is_val: bool, current_item: &Option<String>)
+        -> Result<(Def, Option<String>), ()>
+    {
+        let cx = self.cx;
+
+        // In case we're in a module, try to resolve the relative
+        // path
+        if let Some(id) = self.mod_ids.last() {
+            let result = cx.resolver.borrow_mut()
+                                    .with_scope(*id,
+                |resolver| {
+                    resolver.resolve_str_path_error(DUMMY_SP,
+                                                    &path_str, is_val)
+            });
+
+            if let Ok(result) = result {
+                // In case this is a trait item, skip the
+                // early return and try looking for the trait
+                let value = match result.def {
+                    Def::Method(_) | Def::AssociatedConst(_) => true,
+                    Def::AssociatedTy(_) => false,
+                    Def::Variant(_) => return handle_variant(cx, result.def),
+                    // not a trait item, just return what we found
+                    _ => return Ok((result.def, None))
+                };
+
+                if value != is_val {
+                    return Err(())
+                }
+            } else if let Some(prim) = is_primitive(path_str, is_val) {
+                return Ok((prim, Some(path_str.to_owned())))
+            } else {
+                // If resolution failed, it may still be a method
+                // because methods are not handled by the resolver
+                // If so, bail when we're not looking for a value
+                if !is_val {
+                    return Err(())
+                }
+            }
+
+            // Try looking for methods and associated items
+            let mut split = path_str.rsplitn(2, "::");
+            let item_name = if let Some(first) = split.next() {
+                first
+            } else {
+                return Err(())
+            };
+
+            let mut path = if let Some(second) = split.next() {
+                second.to_owned()
+            } else {
+                return Err(())
+            };
+
+            if path == "self" || path == "Self" {
+                if let Some(name) = current_item.as_ref() {
+                    path = name.clone();
+                }
+            }
+
+            let ty = cx.resolver.borrow_mut()
+                                .with_scope(*id,
+                |resolver| {
+                    resolver.resolve_str_path_error(DUMMY_SP, &path, false)
+            })?;
+            match ty.def {
+                Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => {
+                    let item = cx.tcx.inherent_impls(did)
+                                     .iter()
+                                     .flat_map(|imp| cx.tcx.associated_items(*imp))
+                                     .find(|item| item.ident.name == item_name);
+                    if let Some(item) = item {
+                        let out = match item.kind {
+                            ty::AssociatedKind::Method if is_val => "method",
+                            ty::AssociatedKind::Const if is_val => "associatedconstant",
+                            _ => return Err(())
+                        };
+                        Ok((ty.def, Some(format!("{}.{}", out, item_name))))
+                    } else {
+                        match cx.tcx.type_of(did).sty {
+                            ty::TyAdt(def, _) => {
+                                if let Some(item) = if def.is_enum() {
+                                    def.all_fields().find(|item| item.ident.name == item_name)
+                                } else {
+                                    def.non_enum_variant()
+                                       .fields
+                                       .iter()
+                                       .find(|item| item.ident.name == item_name)
+                                } {
+                                    Ok((ty.def,
+                                        Some(format!("{}.{}",
+                                                     if def.is_enum() {
+                                                         "variant"
+                                                     } else {
+                                                         "structfield"
+                                                     },
+                                                     item.ident))))
+                                } else {
+                                    Err(())
+                                }
+                            }
+                            _ => Err(()),
+                        }
+                    }
+                }
+                Def::Trait(did) => {
+                    let item = cx.tcx.associated_item_def_ids(did).iter()
+                                 .map(|item| cx.tcx.associated_item(*item))
+                                 .find(|item| item.ident.name == item_name);
+                    if let Some(item) = item {
+                        let kind = match item.kind {
+                            ty::AssociatedKind::Const if is_val => "associatedconstant",
+                            ty::AssociatedKind::Type if !is_val => "associatedtype",
+                            ty::AssociatedKind::Method if is_val => {
+                                if item.defaultness.has_value() {
+                                    "method"
+                                } else {
+                                    "tymethod"
+                                }
+                            }
+                            _ => return Err(())
+                        };
+
+                        Ok((ty.def, Some(format!("{}.{}", kind, item_name))))
+                    } else {
+                        Err(())
+                    }
+                }
+                _ => Err(())
+            }
+        } else {
+            Err(())
+        }
+    }
+}
+
+impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstore> {
+    fn fold_item(&mut self, mut item: Item) -> Option<Item> {
+        let item_node_id = if item.is_mod() {
+            if let Some(id) = self.cx.tcx.hir.as_local_node_id(item.def_id) {
+                Some(id)
+            } else {
+                debug!("attempting to fold on a non-local item: {:?}", item);
+                return self.fold_item_recur(item);
+            }
+        } else {
+            None
+        };
+
+        let current_item = match item.inner {
+            ModuleItem(..) => {
+                if item.attrs.inner_docs {
+                    if item_node_id.unwrap() != NodeId::new(0) {
+                        item.name.clone()
+                    } else {
+                        None
+                    }
+                } else {
+                    match self.mod_ids.last() {
+                        Some(parent) if *parent != NodeId::new(0) => {
+                            //FIXME: can we pull the parent module's name from elsewhere?
+                            Some(self.cx.tcx.hir.name(*parent).to_string())
+                        }
+                        _ => None,
+                    }
+                }
+            }
+            ImplItem(Impl { ref for_, .. }) => {
+                for_.def_id().map(|did| self.cx.tcx.item_name(did).to_string())
+            }
+            // we don't display docs on `extern crate` items anyway, so don't process them
+            ExternCrateItem(..) => return self.fold_item_recur(item),
+            ImportItem(Import::Simple(ref name, ..)) => Some(name.clone()),
+            MacroItem(..) => None,
+            _ => item.name.clone(),
+        };
+
+        if item.is_mod() && item.attrs.inner_docs {
+            self.mod_ids.push(item_node_id.unwrap());
+        }
+
+        let cx = self.cx;
+        let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
+
+        for (ori_link, link_range) in markdown_links(&dox) {
+            // bail early for real links
+            if ori_link.contains('/') {
+                continue;
+            }
+            let link = ori_link.replace("`", "");
+            let (def, fragment) = {
+                let mut kind = PathKind::Unknown;
+                let path_str = if let Some(prefix) =
+                    ["struct@", "enum@", "type@",
+                     "trait@", "union@"].iter()
+                                      .find(|p| link.starts_with(**p)) {
+                    kind = PathKind::Type;
+                    link.trim_left_matches(prefix)
+                } else if let Some(prefix) =
+                    ["const@", "static@",
+                     "value@", "function@", "mod@",
+                     "fn@", "module@", "method@"]
+                        .iter().find(|p| link.starts_with(**p)) {
+                    kind = PathKind::Value;
+                    link.trim_left_matches(prefix)
+                } else if link.ends_with("()") {
+                    kind = PathKind::Value;
+                    link.trim_right_matches("()")
+                } else if link.starts_with("macro@") {
+                    kind = PathKind::Macro;
+                    link.trim_left_matches("macro@")
+                } else if link.ends_with('!') {
+                    kind = PathKind::Macro;
+                    link.trim_right_matches('!')
+                } else {
+                    &link[..]
+                }.trim();
+
+                if path_str.contains(|ch: char| !(ch.is_alphanumeric() ||
+                                                  ch == ':' || ch == '_')) {
+                    continue;
+                }
+
+                match kind {
+                    PathKind::Value => {
+                        if let Ok(def) = self.resolve(path_str, true, &current_item) {
+                            def
+                        } else {
+                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            // this could just be a normal link or a broken link
+                            // we could potentially check if something is
+                            // "intra-doc-link-like" and warn in that case
+                            continue;
+                        }
+                    }
+                    PathKind::Type => {
+                        if let Ok(def) = self.resolve(path_str, false, &current_item) {
+                            def
+                        } else {
+                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            // this could just be a normal link
+                            continue;
+                        }
+                    }
+                    PathKind::Unknown => {
+                        // try everything!
+                        if let Some(macro_def) = macro_resolve(cx, path_str) {
+                            if let Ok(type_def) = self.resolve(path_str, false, &current_item) {
+                                let (type_kind, article, type_disambig)
+                                    = type_ns_kind(type_def.0, path_str);
+                                ambiguity_error(cx, &item.attrs, path_str,
+                                                article, type_kind, &type_disambig,
+                                                "a", "macro", &format!("macro@{}", path_str));
+                                continue;
+                            } else if let Ok(value_def) = self.resolve(path_str,
+                                                                       true,
+                                                                       &current_item) {
+                                let (value_kind, value_disambig)
+                                    = value_ns_kind(value_def.0, path_str)
+                                        .expect("struct and mod cases should have been \
+                                                 caught in previous branch");
+                                ambiguity_error(cx, &item.attrs, path_str,
+                                                "a", value_kind, &value_disambig,
+                                                "a", "macro", &format!("macro@{}", path_str));
+                            }
+                            (macro_def, None)
+                        } else if let Ok(type_def) = self.resolve(path_str, false, &current_item) {
+                            // It is imperative we search for not-a-value first
+                            // Otherwise we will find struct ctors for when we are looking
+                            // for structs, and the link won't work.
+                            // if there is something in both namespaces
+                            if let Ok(value_def) = self.resolve(path_str, true, &current_item) {
+                                let kind = value_ns_kind(value_def.0, path_str);
+                                if let Some((value_kind, value_disambig)) = kind {
+                                    let (type_kind, article, type_disambig)
+                                        = type_ns_kind(type_def.0, path_str);
+                                    ambiguity_error(cx, &item.attrs, path_str,
+                                                    article, type_kind, &type_disambig,
+                                                    "a", value_kind, &value_disambig);
+                                    continue;
+                                }
+                            }
+                            type_def
+                        } else if let Ok(value_def) = self.resolve(path_str, true, &current_item) {
+                            value_def
+                        } else {
+                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            // this could just be a normal link
+                            continue;
+                        }
+                    }
+                    PathKind::Macro => {
+                        if let Some(def) = macro_resolve(cx, path_str) {
+                            (def, None)
+                        } else {
+                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            continue
+                        }
+                    }
+                }
+            };
+
+            if let Def::PrimTy(_) = def {
+                item.attrs.links.push((ori_link, None, fragment));
+            } else {
+                let id = register_def(cx, def);
+                item.attrs.links.push((ori_link, Some(id), fragment));
+            }
+        }
+
+        if item.is_mod() && !item.attrs.inner_docs {
+            self.mod_ids.push(item_node_id.unwrap());
+        }
+
+        if item.is_mod() {
+            let ret = self.fold_item_recur(item);
+
+            self.mod_ids.pop();
+
+            ret
+        } else {
+            self.fold_item_recur(item)
+        }
+    }
+}
+
+/// Resolve a string as a macro
+fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
+    use syntax::ext::base::{MacroKind, SyntaxExtension};
+    use syntax::ext::hygiene::Mark;
+    let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
+    let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
+    let mut resolver = cx.resolver.borrow_mut();
+    let mark = Mark::root();
+    let res = resolver
+        .resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false);
+    if let Ok(def) = res {
+        if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
+            return Some(def);
+        }
+    }
+    if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) {
+        return Some(*def);
+    }
+    None
+}
+
+fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
+    if attrs.doc_strings.is_empty() {
+        return DUMMY_SP;
+    }
+    let start = attrs.doc_strings[0].span();
+    let end = attrs.doc_strings.last().expect("No doc strings provided").span();
+    start.to(end)
+}
+
+fn resolution_failure(
+    cx: &DocContext,
+    attrs: &Attributes,
+    path_str: &str,
+    dox: &str,
+    link_range: Option<Range<usize>>,
+) {
+    let sp = span_of_attrs(attrs);
+    let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
+
+    let code_dox = sp.to_src(cx);
+
+    let doc_comment_padding = 3;
+    let mut diag = if let Some(link_range) = link_range {
+        // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
+        //                       ^    ~~~~~~
+        //                       |    link_range
+        //                       last_new_line_offset
+
+        let mut diag;
+        if dox.lines().count() == code_dox.lines().count() {
+            let line_offset = dox[..link_range.start].lines().count();
+            // The span starts in the `///`, so we don't have to account for the leading whitespace
+            let code_dox_len = if line_offset <= 1 {
+                doc_comment_padding
+            } else {
+                // The first `///`
+                doc_comment_padding +
+                    // Each subsequent leading whitespace and `///`
+                    code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
+                        sum + doc_comment_padding + line.len() - line.trim().len()
+                    })
+            };
+
+            // Extract the specific span
+            let sp = sp.from_inner_byte_pos(
+                link_range.start + code_dox_len,
+                link_range.end + code_dox_len,
+            );
+
+            diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
+                                                NodeId::new(0),
+                                                sp,
+                                                &msg);
+            diag.span_label(sp, "cannot be resolved, ignoring");
+        } else {
+            diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
+                                                NodeId::new(0),
+                                                sp,
+                                                &msg);
+
+            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+            let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+
+            // Print the line containing the `link_range` and manually mark it with '^'s
+            diag.note(&format!(
+                "the link appears in this line:\n\n{line}\n\
+                 {indicator: <before$}{indicator:^<found$}",
+                line=line,
+                indicator="",
+                before=link_range.start - last_new_line_offset,
+                found=link_range.len(),
+            ));
+        }
+        diag
+    } else {
+        cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
+                                     NodeId::new(0),
+                                     sp,
+                                     &msg)
+    };
+    diag.help("to escape `[` and `]` characters, just add '\\' before them like \
+               `\\[` or `\\]`");
+    diag.emit();
+}
+
+fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
+                   path_str: &str,
+                   article1: &str, kind1: &str, disambig1: &str,
+                   article2: &str, kind2: &str, disambig2: &str) {
+    let sp = span_of_attrs(attrs);
+    cx.sess()
+      .struct_span_warn(sp,
+                        &format!("`{}` is both {} {} and {} {}",
+                                 path_str, article1, kind1,
+                                 article2, kind2))
+      .help(&format!("try `{}` if you want to select the {}, \
+                      or `{}` if you want to \
+                      select the {}",
+                      disambig1, kind1, disambig2,
+                      kind2))
+      .emit();
+}
+
+/// Given a def, returns its name and disambiguator
+/// for a value namespace
+///
+/// Returns None for things which cannot be ambiguous since
+/// they exist in both namespaces (structs and modules)
+fn value_ns_kind(def: Def, path_str: &str) -> Option<(&'static str, String)> {
+    match def {
+        // structs, variants, and mods exist in both namespaces. skip them
+        Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) | Def::VariantCtor(..) => None,
+        Def::Fn(..)
+            => Some(("function", format!("{}()", path_str))),
+        Def::Method(..)
+            => Some(("method", format!("{}()", path_str))),
+        Def::Const(..)
+            => Some(("const", format!("const@{}", path_str))),
+        Def::Static(..)
+            => Some(("static", format!("static@{}", path_str))),
+        _ => Some(("value", format!("value@{}", path_str))),
+    }
+}
+
+/// Given a def, returns its name, the article to be used, and a disambiguator
+/// for the type namespace
+fn type_ns_kind(def: Def, path_str: &str) -> (&'static str, &'static str, String) {
+    let (kind, article) = match def {
+        // we can still have non-tuple structs
+        Def::Struct(..) => ("struct", "a"),
+        Def::Enum(..) => ("enum", "an"),
+        Def::Trait(..) => ("trait", "a"),
+        Def::Union(..) => ("union", "a"),
+        _ => ("type", "a"),
+    };
+    (kind, article, format!("{}@{}", kind, path_str))
+}
+
+/// Given an enum variant's def, return the def of its enum and the associated fragment
+fn handle_variant(cx: &DocContext, def: Def) -> Result<(Def, Option<String>), ()> {
+    use rustc::ty::DefIdTree;
+
+    let parent = if let Some(parent) = cx.tcx.parent(def.def_id()) {
+        parent
+    } else {
+        return Err(())
+    };
+    let parent_def = Def::Enum(parent);
+    let variant = cx.tcx.expect_variant_def(def);
+    Ok((parent_def, Some(format!("{}.v", variant.name))))
+}
+
+const PRIMITIVES: &[(&str, Def)] = &[
+    ("u8",    Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U8))),
+    ("u16",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U16))),
+    ("u32",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U32))),
+    ("u64",   Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U64))),
+    ("u128",  Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U128))),
+    ("usize", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::Usize))),
+    ("i8",    Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I8))),
+    ("i16",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I16))),
+    ("i32",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I32))),
+    ("i64",   Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I64))),
+    ("i128",  Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I128))),
+    ("isize", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::Isize))),
+    ("f32",   Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F32))),
+    ("f64",   Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F64))),
+    ("str",   Def::PrimTy(hir::PrimTy::TyStr)),
+    ("bool",  Def::PrimTy(hir::PrimTy::TyBool)),
+    ("char",  Def::PrimTy(hir::PrimTy::TyChar)),
+];
+
+fn is_primitive(path_str: &str, is_val: bool) -> Option<Def> {
+    if is_val {
+        None
+    } else {
+        PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1)
+    }
+}
index aa4acaf75bf31953220f1cddf068eb26aada8365..16251877bb10637faa7a993d5a012ea8f4e08ca4 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Contains information about "passes", used to modify crate information during the documentation
+//! process.
+
 use rustc::hir::def_id::DefId;
 use rustc::middle::privacy::AccessLevels;
 use rustc::util::nodemap::DefIdSet;
 use std::mem;
+use std::fmt;
 
 use clean::{self, GetDefId, Item};
+use core::DocContext;
 use fold;
 use fold::StripItem;
 
 mod collapse_docs;
-pub use self::collapse_docs::collapse_docs;
+pub use self::collapse_docs::COLLAPSE_DOCS;
 
 mod strip_hidden;
-pub use self::strip_hidden::strip_hidden;
+pub use self::strip_hidden::STRIP_HIDDEN;
 
 mod strip_private;
-pub use self::strip_private::strip_private;
+pub use self::strip_private::STRIP_PRIVATE;
 
 mod strip_priv_imports;
-pub use self::strip_priv_imports::strip_priv_imports;
+pub use self::strip_priv_imports::STRIP_PRIV_IMPORTS;
 
 mod unindent_comments;
-pub use self::unindent_comments::unindent_comments;
+pub use self::unindent_comments::UNINDENT_COMMENTS;
 
 mod propagate_doc_cfg;
-pub use self::propagate_doc_cfg::propagate_doc_cfg;
+pub use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
+
+mod collect_intra_doc_links;
+pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
+
+/// Represents a single pass.
+#[derive(Copy, Clone)]
+pub enum Pass {
+    /// An "early pass" is run in the compiler context, and can gather information about types and
+    /// traits and the like.
+    EarlyPass {
+        name: &'static str,
+        pass: fn(clean::Crate, &DocContext) -> clean::Crate,
+        description: &'static str,
+    },
+    /// A "late pass" is run between crate cleaning and page generation.
+    LatePass {
+        name: &'static str,
+        pass: fn(clean::Crate) -> clean::Crate,
+        description: &'static str,
+    },
+}
+
+impl fmt::Debug for Pass {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut dbg = match *self {
+            Pass::EarlyPass { .. } => f.debug_struct("EarlyPass"),
+            Pass::LatePass { .. } => f.debug_struct("LatePass"),
+        };
+
+        dbg.field("name", &self.name())
+           .field("pass", &"...")
+           .field("description", &self.description())
+           .finish()
+    }
+}
 
-type Pass = (
-    &'static str,                     // name
-    fn(clean::Crate) -> clean::Crate, // fn
-    &'static str,
-); // description
+impl Pass {
+    /// Constructs a new early pass.
+    pub const fn early(name: &'static str,
+                       pass: fn(clean::Crate, &DocContext) -> clean::Crate,
+                       description: &'static str) -> Pass {
+        Pass::EarlyPass { name, pass, description }
+    }
 
+    /// Constructs a new late pass.
+    pub const fn late(name: &'static str,
+                      pass: fn(clean::Crate) -> clean::Crate,
+                      description: &'static str) -> Pass {
+        Pass::LatePass { name, pass, description }
+    }
+
+    /// Returns the name of this pass.
+    pub fn name(self) -> &'static str {
+        match self {
+            Pass::EarlyPass { name, .. } |
+                Pass::LatePass { name, .. } => name,
+        }
+    }
+
+    /// Returns the description of this pass.
+    pub fn description(self) -> &'static str {
+        match self {
+            Pass::EarlyPass { description, .. } |
+                Pass::LatePass { description, .. } => description,
+        }
+    }
+
+    /// If this pass is an early pass, returns the pointer to its function.
+    pub fn early_fn(self) -> Option<fn(clean::Crate, &DocContext) -> clean::Crate> {
+        match self {
+            Pass::EarlyPass { pass, .. } => Some(pass),
+            _ => None,
+        }
+    }
+
+    /// If this pass is a late pass, returns the pointer to its function.
+    pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
+        match self {
+            Pass::LatePass { pass, .. } => Some(pass),
+            _ => None,
+        }
+    }
+}
+
+/// The full list of passes.
 pub const PASSES: &'static [Pass] = &[
-    (
-        "strip-hidden",
-        strip_hidden,
-        "strips all doc(hidden) items from the output",
-    ),
-    (
-        "unindent-comments",
-        unindent_comments,
-        "removes excess indentation on comments in order for markdown to like it",
-    ),
-    (
-        "collapse-docs",
-        collapse_docs,
-        "concatenates all document attributes into one document attribute",
-    ),
-    (
-        "strip-private",
-        strip_private,
-        "strips all private items from a crate which cannot be seen externally, \
-         implies strip-priv-imports",
-    ),
-    (
-        "strip-priv-imports",
-        strip_priv_imports,
-        "strips all private import statements (`use`, `extern crate`) from a crate",
-    ),
-    (
-        "propagate-doc-cfg",
-        propagate_doc_cfg,
-        "propagates `#[doc(cfg(...))]` to child items",
-    ),
+    STRIP_HIDDEN,
+    UNINDENT_COMMENTS,
+    COLLAPSE_DOCS,
+    STRIP_PRIVATE,
+    STRIP_PRIV_IMPORTS,
+    PROPAGATE_DOC_CFG,
+    COLLECT_INTRA_DOC_LINKS,
 ];
 
+/// The list of passes run by default.
 pub const DEFAULT_PASSES: &'static [&'static str] = &[
     "strip-hidden",
     "strip-private",
+    "collect-intra-doc-links",
     "collapse-docs",
     "unindent-comments",
     "propagate-doc-cfg",
 ];
 
+/// The list of default passes run with `--document-private-items` is passed to rustdoc.
 pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
     "strip-priv-imports",
+    "collect-intra-doc-links",
     "collapse-docs",
     "unindent-comments",
     "propagate-doc-cfg",
 ];
 
+/// A shorthand way to refer to which set of passes to use, based on the presence of
+/// `--no-defaults` or `--document-private-items`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum DefaultPassOption {
     Default,
@@ -97,6 +162,7 @@ pub enum DefaultPassOption {
     None,
 }
 
+/// Returns the given default set of passes.
 pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] {
     match default_set {
         DefaultPassOption::Default => DEFAULT_PASSES,
@@ -105,6 +171,11 @@ pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] {
     }
 }
 
+/// If the given name matches a known pass, returns its information.
+pub fn find_pass(pass_name: &str) -> Option<Pass> {
+    PASSES.iter().find(|p| p.name() == pass_name).cloned()
+}
+
 struct Stripper<'a> {
     retained: &'a mut DefIdSet,
     access_levels: &'a AccessLevels<DefId>,
index 572a8d3f470f2ac24ad038d5b9e2a94c4154786d..69093846302a7c65da5f60b6811aebcf240860a8 100644 (file)
 use clean::{Crate, Item};
 use clean::cfg::Cfg;
 use fold::DocFolder;
+use passes::Pass;
+
+pub const PROPAGATE_DOC_CFG: Pass =
+    Pass::late("propagate-doc-cfg", propagate_doc_cfg,
+        "propagates `#[doc(cfg(...))]` to child items");
 
 pub fn propagate_doc_cfg(cr: Crate) -> Crate {
     CfgPropagator { parent_cfg: None }.fold_crate(cr)
index 279c9603703cde34abbb46fc7c921644b1092fbb..cc0b6fb6d67053b16219e896f9209920177e395b 100644 (file)
 
 use clean::{self, AttributesExt, NestedAttributesExt};
 use clean::Item;
+use core::DocContext;
 use fold;
 use fold::DocFolder;
 use fold::StripItem;
-use passes::ImplStripper;
+use passes::{ImplStripper, Pass};
+
+pub const STRIP_HIDDEN: Pass =
+    Pass::early("strip-hidden", strip_hidden,
+                "strips all doc(hidden) items from the output");
 
 /// Strip items marked `#[doc(hidden)]`
-pub fn strip_hidden(krate: clean::Crate) -> clean::Crate {
+pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
     let mut retained = DefIdSet();
 
     // strip all #[doc(hidden)] items
index c4640839923bdc2d781decc786d16a48f8c2bd1d..f01c333d742d380fa1f3b2591267ba5933ffd62d 100644 (file)
@@ -9,9 +9,13 @@
 // except according to those terms.
 
 use clean;
+use core::DocContext;
 use fold::DocFolder;
-use passes::ImportStripper;
+use passes::{ImportStripper, Pass};
 
-pub fn strip_priv_imports(krate: clean::Crate)  -> clean::Crate {
+pub const STRIP_PRIV_IMPORTS: Pass = Pass::early("strip-priv-imports", strip_priv_imports,
+     "strips all private import statements (`use`, `extern crate`) from a crate");
+
+pub fn strip_priv_imports(krate: clean::Crate, _: &DocContext)  -> clean::Crate {
     ImportStripper.fold_crate(krate)
 }
index 45f706590e32e558d6a9af4d001b60402ff75339..3b17a768ffdee6fd6ca8d5bb0a0d91a9dfa86c9c 100644 (file)
 use rustc::util::nodemap::DefIdSet;
 
 use clean;
+use core::DocContext;
 use fold::DocFolder;
-use passes::{ImplStripper, ImportStripper, Stripper};
+use passes::{ImplStripper, ImportStripper, Stripper, Pass};
+
+pub const STRIP_PRIVATE: Pass =
+    Pass::early("strip-private", strip_private,
+        "strips all private items from a crate which cannot be seen externally, \
+         implies strip-priv-imports");
 
 /// Strip private items from the point of view of a crate or externally from a
 /// crate, specified by the `xcrate` flag.
-pub fn strip_private(mut krate: clean::Crate) -> clean::Crate {
+pub fn strip_private(mut krate: clean::Crate, _: &DocContext) -> clean::Crate {
     // This stripper collects all *retained* nodes.
     let mut retained = DefIdSet();
     let access_levels = krate.access_levels.clone();
index 2510ec011b64ca499227e915100e538489fb1fd3..6d875c107c874f2f719aab039f6f8fba791be90b 100644 (file)
 
 use clean::{self, DocFragment, Item};
 use fold::{self, DocFolder};
+use passes::Pass;
+
+pub const UNINDENT_COMMENTS: Pass =
+    Pass::late("unindent-comments", unindent_comments,
+        "removes excess indentation on comments in order for markdown to like it");
 
 pub fn unindent_comments(krate: clean::Crate) -> clean::Crate {
     CommentCleaner.fold_crate(krate)
index 2966b9e9819b4771724bf3731f6fd9fa7194ad37..d8e382f6998ceb1b66e108d7770a04c8feabe92f 100644 (file)
@@ -42,7 +42,7 @@
 use errors::emitter::ColorConfig;
 
 use clean::Attributes;
-use html::markdown;
+use html::markdown::{self, ErrorCodes, LangString};
 
 #[derive(Clone, Default)]
 pub struct TestOptions {
@@ -73,7 +73,7 @@ pub fn run(input_path: &Path,
         maybe_sysroot: maybe_sysroot.clone().or_else(
             || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
         search_paths: libs.clone(),
-        crate_types: vec![config::CrateTypeDylib],
+        crate_types: vec![config::CrateType::Dylib],
         cg: cg.clone(),
         externs: externs.clone(),
         unstable_features: UnstableFeatures::from_environment(),
@@ -83,7 +83,7 @@ pub fn run(input_path: &Path,
             ..config::basic_debugging_options()
         },
         edition,
-        ..config::basic_options().clone()
+        ..config::Options::default()
     };
     driver::spawn_thread_pool(sessopts, |sessopts| {
         let codemap = Lrc::new(CodeMap::new(sessopts.file_path_mapping()));
@@ -145,7 +145,8 @@ pub fn run(input_path: &Path,
             let mut hir_collector = HirCollector {
                 sess: &sess,
                 collector: &mut collector,
-                map: &map
+                map: &map,
+                codes: ErrorCodes::from(sess.opts.unstable_features.is_nightly_build()),
             };
             hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
                 intravisit::walk_crate(this, krate);
@@ -215,7 +216,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
         maybe_sysroot: maybe_sysroot.or_else(
             || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
         search_paths: libs,
-        crate_types: vec![config::CrateTypeExecutable],
+        crate_types: vec![config::CrateType::Executable],
         output_types: outputs,
         externs,
         cg: config::CodegenOptions {
@@ -229,7 +230,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
             ..config::basic_debugging_options()
         },
         edition,
-        ..config::basic_options().clone()
+        ..config::Options::default()
     };
 
     // Shuffle around a few input and output handles here. We're going to pass
@@ -533,10 +534,8 @@ fn generate_name(&self, line: usize, filename: &FileName) -> String {
         format!("{} - {} (line {})", filename, self.names.join("::"), line)
     }
 
-    pub fn add_test(&mut self, test: String,
-                    should_panic: bool, no_run: bool, should_ignore: bool,
-                    as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
-                    line: usize, filename: FileName, allow_fail: bool) {
+    pub fn add_test(&mut self, test: String, config: LangString, line: usize) {
+        let filename = self.get_filename();
         let name = self.generate_name(line, &filename);
         let cfgs = self.cfgs.clone();
         let libs = self.libs.clone();
@@ -551,10 +550,10 @@ pub fn add_test(&mut self, test: String,
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
                 name: testing::DynTestName(name.clone()),
-                ignore: should_ignore,
+                ignore: config.ignore,
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
-                allow_fail,
+                allow_fail: config.allow_fail,
             },
             testfn: testing::DynTestFn(box move || {
                 let panic = io::set_panic(None);
@@ -572,11 +571,11 @@ pub fn add_test(&mut self, test: String,
                                  libs,
                                  cg,
                                  externs,
-                                 should_panic,
-                                 no_run,
-                                 as_test_harness,
-                                 compile_fail,
-                                 error_codes,
+                                 config.should_panic,
+                                 config.no_run,
+                                 config.test_harness,
+                                 config.compile_fail,
+                                 config.error_codes,
                                  &opts,
                                  maybe_sysroot,
                                  linker,
@@ -604,7 +603,7 @@ pub fn set_position(&mut self, position: Span) {
         self.position = position;
     }
 
-    pub fn get_filename(&self) -> FileName {
+    fn get_filename(&self) -> FileName {
         if let Some(ref codemap) = self.codemap {
             let filename = codemap.span_to_filename(self.position);
             if let FileName::Real(ref filename) = filename {
@@ -664,7 +663,8 @@ pub fn register_header(&mut self, name: &str, level: u32) {
 struct HirCollector<'a, 'hir: 'a> {
     sess: &'a session::Session,
     collector: &'a mut Collector,
-    map: &'a hir::map::Map<'hir>
+    map: &'a hir::map::Map<'hir>,
+    codes: ErrorCodes,
 }
 
 impl<'a, 'hir> HirCollector<'a, 'hir> {
@@ -689,10 +689,12 @@ fn visit_testable<F: FnOnce(&mut Self)>(&mut self,
         // the collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us
         if let Some(doc) = attrs.collapsed_doc_value() {
-            markdown::find_testable_code(&doc,
-                                         self.collector,
-                                         attrs.span.unwrap_or(DUMMY_SP),
-                                         Some(self.sess));
+            self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP));
+            let res = markdown::find_testable_code(&doc, self.collector, self.codes);
+            if let Err(err) = res {
+                self.sess.diagnostic().span_warn(attrs.span.unwrap_or(DUMMY_SP),
+                    &err.to_string());
+            }
         }
 
         nested(self);
index 09d304b71a2c1627adb424e0742b253b256945f3..e2c935e2f6921fb6615eb9982648fb3afc94fcf0 100644 (file)
 // also, is there some reason that this doesn't use the 'visit'
 // framework from syntax?
 
-pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
+pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
     pub module: Module,
     pub attrs: hir::HirVec<ast::Attribute>,
-    pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>,
+    pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>,
     view_item_stack: FxHashSet<ast::NodeId>,
     inlining: bool,
     /// Is the current module and all of its parents public?
@@ -49,8 +49,10 @@ pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
     exact_paths: Option<FxHashMap<DefId, Vec<String>>>,
 }
 
-impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
-    pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> RustdocVisitor<'a, 'tcx, 'rcx> {
+impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
+    pub fn new(
+        cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>
+    ) -> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
         // If the root is re-exported, terminate all recursion.
         let mut stack = FxHashSet();
         stack.insert(ast::CRATE_NODE_ID);
@@ -105,8 +107,8 @@ pub fn visit(&mut self, krate: &hir::Crate) {
     }
 
     pub fn visit_variant_data(&mut self, item: &hir::Item,
-                            name: ast::Name, sd: &hir::VariantData,
-                            generics: &hir::Generics) -> Struct {
+                              name: ast::Name, sd: &hir::VariantData,
+                              generics: &hir::Generics) -> Struct {
         debug!("Visiting struct");
         let struct_type = struct_type_from_def(&*sd);
         Struct {
index 4c773fc1dd78b7e1b7ae29b0fc8c489a836cd918..10a4e69dcc6cd901fb540ce5663ea4aa547eb284 100644 (file)
@@ -22,8 +22,8 @@
 
 /// Similar to `librustc_privacy::EmbargoVisitor`, but also takes
 /// specific rustdoc annotations into account (i.e. `doc(hidden)`)
-pub struct LibEmbargoVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
-    cx: &'a ::core::DocContext<'a, 'tcx, 'rcx>,
+pub struct LibEmbargoVisitor<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
+    cx: &'a ::core::DocContext<'a, 'tcx, 'rcx, 'cstore>,
     // Accessibility levels for reachable nodes
     access_levels: RefMut<'a, AccessLevels<DefId>>,
     // Previous accessibility level, None means unreachable
@@ -32,8 +32,10 @@ pub struct LibEmbargoVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
     visited_mods: FxHashSet<DefId>,
 }
 
-impl<'a, 'tcx, 'rcx> LibEmbargoVisitor<'a, 'tcx, 'rcx> {
-    pub fn new(cx: &'a ::core::DocContext<'a, 'tcx, 'rcx>) -> LibEmbargoVisitor<'a, 'tcx, 'rcx> {
+impl<'a, 'tcx, 'rcx, 'cstore> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> {
+    pub fn new(
+        cx: &'a ::core::DocContext<'a, 'tcx, 'rcx, 'cstore>
+    ) -> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> {
         LibEmbargoVisitor {
             cx,
             access_levels: cx.access_levels.borrow_mut(),
index 7341dec5156d4fb93474929aab4f6ccc8bc1754b..ed94194ffcc05be5411eb9ca3cd5fb397e4f8fab 100644 (file)
@@ -46,58 +46,67 @@ pub trait Encoder {
 
     // Compound types:
     fn emit_enum<F>(&mut self, _name: &str, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
-
-    fn emit_enum_variant<F>(&mut self, _v_name: &str,
-                            v_id: usize,
-                            _len: usize,
-                            f: F) -> Result<(), Self::Error>
         where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
+
+    fn emit_enum_variant<F>(&mut self, _v_name: &str, v_id: usize, _len: usize, f: F)
+        -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
     {
         self.emit_usize(v_id)?;
         f(self)
     }
-    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F)
-                                -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
 
-    fn emit_enum_struct_variant<F>(&mut self, v_name: &str,
-                                   v_id: usize,
-                                   len: usize,
-                                   f: F) -> Result<(), Self::Error>
+    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F) -> Result<(), Self::Error>
         where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
+
+    fn emit_enum_struct_variant<F>(&mut self, v_name: &str, v_id: usize, len: usize, f: F)
+        -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
     {
         self.emit_enum_variant(v_name, v_id, len, f)
     }
-    fn emit_enum_struct_variant_field<F>(&mut self,
-                                         _f_name: &str,
-                                         f_idx: usize,
-                                         f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+
+    fn emit_enum_struct_variant_field<F>(&mut self, _f_name: &str, f_idx: usize, f: F)
+        -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
     {
         self.emit_enum_variant_arg(f_idx, f)
     }
 
-    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F)
-                      -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
+
     fn emit_struct_field<F>(&mut self, _f_name: &str, _f_idx: usize, f: F)
-                            -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+        -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
 
     fn emit_tuple<F>(&mut self, _len: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
+
     fn emit_tuple_arg<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
 
-    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F)
-                            -> Result<(), Self::Error>
+    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> Result<(), Self::Error>
         where F: FnOnce(&mut Self) -> Result<(), Self::Error>
     {
         self.emit_tuple(len, f)
     }
-    fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F)
-                                -> Result<(), Self::Error>
+
+    fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F) -> Result<(), Self::Error>
         where F: FnOnce(&mut Self) -> Result<(), Self::Error>
     {
         self.emit_tuple_arg(f_idx, f)
@@ -109,13 +118,14 @@ fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error>
     {
         self.emit_enum("Option", f)
     }
+
     fn emit_option_none(&mut self) -> Result<(), Self::Error> {
         self.emit_enum_variant("None", 0, 0, |_| Ok(()))
     }
+
     fn emit_option_some<F>(&mut self, f: F) -> Result<(), Self::Error>
         where F: FnOnce(&mut Self) -> Result<(), Self::Error>
     {
-
         self.emit_enum_variant("Some", 1, 1, f)
     }
 
@@ -125,8 +135,12 @@ fn emit_seq<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
         self.emit_usize(len)?;
         f(self)
     }
+
     fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
 
     fn emit_map<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
         where F: FnOnce(&mut Self) -> Result<(), Self::Error>
@@ -134,10 +148,18 @@ fn emit_map<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
         self.emit_usize(len)?;
         f(self)
     }
+
     fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
+
     fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
-        where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>
+    {
+        f(self)
+    }
 }
 
 pub trait Decoder {
@@ -165,59 +187,67 @@ pub trait Decoder {
 
     // Compound types:
     fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
 
-    fn read_enum_variant<T, F>(&mut self, _names: &[&str], mut f: F)
-                               -> Result<T, Self::Error>
+    fn read_enum_variant<T, F>(&mut self, _names: &[&str], mut f: F) -> Result<T, Self::Error>
         where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
     {
         let disr = self.read_usize()?;
         f(self, disr)
     }
-    fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F)
-                                   -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
 
-    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F)
-                                      -> Result<T, Self::Error>
+    fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
+
+    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, Self::Error>
         where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
     {
         self.read_enum_variant(names, f)
     }
-    fn read_enum_struct_variant_field<T, F>(&mut self,
-                                            _f_name: &str,
-                                            f_idx: usize,
-                                            f: F)
-                                            -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+
+    fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, f_idx: usize, f: F)
+        -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error>
     {
         self.read_enum_variant_arg(f_idx, f)
     }
 
-    fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F)
-                         -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
-    fn read_struct_field<T, F>(&mut self,
-                               _f_name: &str,
-                               _f_idx: usize,
-                               f: F)
-                               -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
+    fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
+
+    fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, f: F)
+        -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
 
     fn read_tuple<T, F>(&mut self, _len: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
-    fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F)
-                            -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
+
+    fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
 
-    fn read_tuple_struct<T, F>(&mut self, _s_name: &str, len: usize, f: F)
-                               -> Result<T, Self::Error>
+    fn read_tuple_struct<T, F>(&mut self, _s_name: &str, len: usize, f: F) -> Result<T, Self::Error>
         where F: FnOnce(&mut Self) -> Result<T, Self::Error>
     {
         self.read_tuple(len, f)
     }
-    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F)
-                                   -> Result<T, Self::Error>
+
+    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, Self::Error>
         where F: FnOnce(&mut Self) -> Result<T, Self::Error>
     {
         self.read_tuple_arg(a_idx, f)
@@ -244,8 +274,12 @@ fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
         let len = self.read_usize()?;
         f(self, len)
     }
+
     fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
 
     fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
         where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
@@ -253,12 +287,18 @@ fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
         let len = self.read_usize()?;
         f(self, len)
     }
-    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F)
-                              -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
-    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F)
-                              -> Result<T, Self::Error>
-        where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
+
+    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
+
+    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
+    {
+        f(self)
+    }
 
     // Failure
     fn error(&mut self, err: &str) -> Self::Error;
@@ -567,9 +607,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Vec<T>, D::Error> {
     }
 }
 
-impl<'a, T:Encodable> Encodable for Cow<'a, [T]>
-where [T]: ToOwned<Owned = Vec<T>>
-{
+impl<'a, T:Encodable> Encodable for Cow<'a, [T]> where [T]: ToOwned<Owned = Vec<T>> {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
@@ -580,9 +618,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T:Decodable+ToOwned> Decodable for Cow<'static, [T]>
-where [T]: ToOwned<Owned = Vec<T>>
-{
+impl<T:Decodable+ToOwned> Decodable for Cow<'static, [T]> where [T]: ToOwned<Owned = Vec<T>> {
     fn decode<D: Decoder>(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
@@ -685,8 +721,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<($($name,)*), D::Error> {
                 let len: usize = count_idents!($($name,)*);
                 d.read_tuple(len, |d| {
                     let mut i = 0;
-                    let ret = ($(d.read_tuple_arg({ i+=1; i-1 },
-                                                  |d| -> Result<$name,D::Error> {
+                    let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> {
                         Decodable::decode(d)
                     })?,)*);
                     Ok(ret)
@@ -778,13 +813,11 @@ pub trait SpecializationError {
     /// `T` is the type being encoded/decoded, and
     /// the arguments are the names of the trait
     /// and method that should've been overridden.
-    fn not_found<S, T: ?Sized>(trait_name: &'static str,
-                               method_name: &'static str) -> Self;
+    fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> Self;
 }
 
 impl<E> SpecializationError for E {
-    default fn not_found<S, T: ?Sized>(trait_name: &'static str,
-                                       method_name: &'static str) -> E {
+    default fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> E {
         panic!("missing specialization: `<{} as {}<{}>>::{}` not overridden",
                unsafe { intrinsics::type_name::<S>() },
                trait_name,
index 5a2dce5930a4b959eac9b7b0aee6141604b175da..5348c9a0f349842e057985b7fdfce779d3714082 100644 (file)
@@ -22,7 +22,6 @@ core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
-std_unicode = { path = "../libstd_unicode" }
 unwind = { path = "../libunwind" }
 
 [dev-dependencies]
index 8db365cd21d67938be2bbca12cfee14a3fded4cd..b9aba1e9cab321d979430c921d3960cfacf38ac3 100644 (file)
@@ -125,8 +125,7 @@ fn default_alloc_error_hook(layout: Layout) {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[cfg_attr(stage0, lang = "oom")]
-#[cfg_attr(not(stage0), alloc_error_handler)]
+#[alloc_error_handler]
 #[unstable(feature = "alloc_internals", issue = "0")]
 pub fn rust_oom(layout: Layout) -> ! {
     let hook = HOOK.load(Ordering::SeqCst);
index 376410677346cea1be104a402d4334d0e734880f..0c8e95aa4262409b48a57f4834528781d36fb48f 100644 (file)
@@ -154,180 +154,6 @@ pub trait AsciiExt {
     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
     fn make_ascii_lowercase(&mut self);
-
-    /// Checks if the value is an ASCII alphabetic character:
-    /// U+0041 'A' ... U+005A 'Z' or U+0061 'a' ... U+007A 'z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII alphabetic.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_alphabetic)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_alphabetic)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII uppercase character:
-    /// U+0041 'A' ... U+005A 'Z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII uppercase.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_uppercase)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_uppercase)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII lowercase character:
-    /// U+0061 'a' ... U+007A 'z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII lowercase.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_lowercase)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_lowercase)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII alphanumeric character:
-    /// U+0041 'A' ... U+005A 'Z', U+0061 'a' ... U+007A 'z', or
-    /// U+0030 '0' ... U+0039 '9'.
-    /// For strings, true if all characters in the string are
-    /// ASCII alphanumeric.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_alphanumeric)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_alphanumeric)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII decimal digit:
-    /// U+0030 '0' ... U+0039 '9'.
-    /// For strings, true if all characters in the string are
-    /// ASCII digits.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_digit)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_digit)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_digit(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII hexadecimal digit:
-    /// U+0030 '0' ... U+0039 '9', U+0041 'A' ... U+0046 'F', or
-    /// U+0061 'a' ... U+0066 'f'.
-    /// For strings, true if all characters in the string are
-    /// ASCII hex digits.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_hexdigit)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_hexdigit)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII punctuation character:
-    ///
-    /// U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`
-    /// U+003A ... U+0040 `: ; < = > ? @`
-    /// U+005B ... U+0060 ``[ \\ ] ^ _ ` ``
-    /// U+007B ... U+007E `{ | } ~`
-    ///
-    /// For strings, true if all characters in the string are
-    /// ASCII punctuation.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_punctuation)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_punctuation)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII graphic character:
-    /// U+0021 '!' ... U+007E '~'.
-    /// For strings, true if all characters in the string are
-    /// ASCII graphic characters.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_graphic)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_graphic)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII whitespace character:
-    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
-    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
-    /// For strings, true if all characters in the string are
-    /// ASCII whitespace.
-    ///
-    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
-    /// whitespace][infra-aw].  There are several other definitions in
-    /// wide use.  For instance, [the POSIX locale][pct] includes
-    /// U+000B VERTICAL TAB as well as all the above characters,
-    /// but—from the very same specification—[the default rule for
-    /// "field splitting" in the Bourne shell][bfs] considers *only*
-    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
-    ///
-    /// If you are writing a program that will process an existing
-    /// file format, check what that format's definition of whitespace is
-    /// before using this function.
-    ///
-    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
-    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
-    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_whitespace)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_whitespace)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII control character:
-    /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
-    /// Note that most ASCII whitespace characters are control
-    /// characters, but SPACE is not.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_control)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_control)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
 macro_rules! delegating_ascii_methods {
@@ -352,47 +178,12 @@ fn eq_ignore_ascii_case(&self, o: &Self) -> bool { self.eq_ignore_ascii_case(o)
     }
 }
 
-macro_rules! delegating_ascii_ctype_methods {
-    () => {
-        #[inline]
-        fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
-
-        #[inline]
-        fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
-
-        #[inline]
-        fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
-
-        #[inline]
-        fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
-
-        #[inline]
-        fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
-
-        #[inline]
-        fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
-
-        #[inline]
-        fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
-
-        #[inline]
-        fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
-
-        #[inline]
-        fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
-
-        #[inline]
-        fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
 impl AsciiExt for u8 {
     type Owned = u8;
 
     delegating_ascii_methods!();
-    delegating_ascii_ctype_methods!();
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -401,7 +192,6 @@ impl AsciiExt for char {
     type Owned = char;
 
     delegating_ascii_methods!();
-    delegating_ascii_ctype_methods!();
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -410,56 +200,6 @@ impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
 
     delegating_ascii_methods!();
-
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_alphabetic())
-    }
-
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_uppercase())
-    }
-
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_lowercase())
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_alphanumeric())
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_digit())
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_hexdigit())
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_punctuation())
-    }
-
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_graphic())
-    }
-
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_whitespace())
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_control())
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -468,54 +208,4 @@ impl AsciiExt for str {
     type Owned = String;
 
     delegating_ascii_methods!();
-
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphabetic())
-    }
-
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_uppercase())
-    }
-
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_lowercase())
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphanumeric())
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_digit())
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_hexdigit())
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_punctuation())
-    }
-
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_graphic())
-    }
-
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_whitespace())
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_control())
-    }
 }
index 754e2bbc4122b7f127b679fbaf3e5bda488ac6a3..b2777f5c48541f13171259a711e7885a159da6b4 100644 (file)
@@ -642,6 +642,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[stable(feature = "cstring_into", since = "1.7.0")]
 impl From<CString> for Vec<u8> {
+    /// Converts a [`CString`] into a [`Vec`]`<u8>`.
+    ///
+    /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
+    ///
+    /// [`Vec`]: ../vec/struct.Vec.html
+    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: CString) -> Vec<u8> {
         s.into_bytes()
@@ -700,6 +706,10 @@ fn from(s: &'a CStr) -> Box<CStr> {
 
 #[stable(feature = "c_string_from_box", since = "1.18.0")]
 impl From<Box<CStr>> for CString {
+    /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: Box<CStr>) -> CString {
         s.into_c_string()
@@ -716,6 +726,10 @@ fn clone(&self) -> Self {
 
 #[stable(feature = "box_from_c_string", since = "1.20.0")]
 impl From<CString> for Box<CStr> {
+    /// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Box`]: ../boxed/struct.Box.html
     #[inline]
     fn from(s: CString) -> Box<CStr> {
         s.into_boxed_c_str()
@@ -748,6 +762,10 @@ fn from(s: &'a CString) -> Cow<'a, CStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Arc<CStr> {
+    /// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Arc`]: ../sync/struct.Arc.html
     #[inline]
     fn from(s: CString) -> Arc<CStr> {
         let arc: Arc<[u8]> = Arc::from(s.into_inner());
@@ -766,6 +784,10 @@ fn from(s: &CStr) -> Arc<CStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
+    /// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Rc`]: ../rc/struct.Rc.html
     #[inline]
     fn from(s: CString) -> Rc<CStr> {
         let rc: Rc<[u8]> = Rc::from(s.into_inner());
@@ -839,6 +861,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<NulError> for io::Error {
+    /// Converts a [`NulError`] into a [`io::Error`].
+    ///
+    /// [`NulError`]: ../ffi/struct.NulError.html
+    /// [`io::Error`]: ../io/struct.Error.html
     fn from(_: NulError) -> io::Error {
         io::Error::new(io::ErrorKind::InvalidInput,
                        "data provided contains a nul byte")
index b1c6e7af693d0a00eae72517ef9fe984dfe644d9..9e501a84e05ec6e9176a5904c31f4674dfb746e0 100644 (file)
@@ -348,6 +348,12 @@ pub fn into_boxed_os_str(self) -> Box<OsStr> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for OsString {
+    /// Converts a [`String`] into a [`OsString`].
+    ///
+    /// The conversion copies the data, and includes an allocation on the heap.
+    ///
+    /// [`String`]: ../string/struct.String.html
+    /// [`OsString`]: struct.OsString.html
     fn from(s: String) -> OsString {
         OsString { inner: Buf::from_string(s) }
     }
@@ -630,6 +636,10 @@ fn from(s: &'a OsStr) -> Box<OsStr> {
 
 #[stable(feature = "os_string_from_box", since = "1.18.0")]
 impl From<Box<OsStr>> for OsString {
+    /// Converts a `Box<OsStr>` into a `OsString` without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     fn from(boxed: Box<OsStr>) -> OsString {
         boxed.into_os_string()
     }
@@ -637,6 +647,10 @@ fn from(boxed: Box<OsStr>) -> OsString {
 
 #[stable(feature = "box_from_os_string", since = "1.20.0")]
 impl From<OsString> for Box<OsStr> {
+    /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     fn from(s: OsString) -> Box<OsStr> {
         s.into_boxed_os_str()
     }
@@ -652,6 +666,10 @@ fn clone(&self) -> Self {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Arc<OsStr> {
+    /// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
+    ///
+    /// [`Arc`]: ../sync/struct.Arc.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Arc<OsStr> {
         let arc = s.inner.into_arc();
@@ -670,6 +688,10 @@ fn from(s: &OsStr) -> Arc<OsStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
+    /// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
+    ///
+    /// [`Rc`]: ../rc/struct.Rc.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Rc<OsStr> {
         let rc = s.inner.into_rc();
index c1cc36f3b419a2364eeef8c4df4d608e075d1a06..12ea1ea9f9d49cc56a0ef0c4b3890647cd6a5013 100644 (file)
@@ -108,9 +108,9 @@ pub fn get_task_cx<F, R>(f: F) -> R
 
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Polls a future in the current thread-local task context.
-pub fn poll_in_task_cx<F>(f: &mut PinMut<F>) -> Poll<F::Output>
+pub fn poll_in_task_cx<F>(f: PinMut<F>) -> Poll<F::Output>
 where
     F: Future
 {
-    get_task_cx(|cx| f.reborrow().poll(cx))
+    get_task_cx(|cx| f.poll(cx))
 }
index 2babf508fdcc3b524fc0f12e9e6717cdb2b78ad8..03c97de6ec1e9b8418c9da79ded78dca8777d2d0 100644 (file)
@@ -154,33 +154,6 @@ pub fn get_ref(&self) -> &R { &self.inner }
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
 
-    /// Returns `true` if there are no bytes in the internal buffer.
-    ///
-    /// # Examples
-    //
-    /// ```no_run
-    /// # #![feature(bufreader_is_empty)]
-    /// use std::io::BufReader;
-    /// use std::io::BufRead;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f1 = File::open("log.txt")?;
-    ///     let mut reader = BufReader::new(f1);
-    ///     assert!(reader.is_empty());
-    ///
-    ///     if reader.fill_buf()?.len() > 0 {
-    ///         assert!(!reader.is_empty());
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
-    pub fn is_empty(&self) -> bool {
-        self.buffer().is_empty()
-    }
-
     /// Returns a reference to the internally buffered data.
     ///
     /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
@@ -1265,25 +1238,6 @@ fn test_short_reads() {
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
-    #[test]
-    #[allow(deprecated)]
-    fn read_char_buffered() {
-        let buf = [195, 159];
-        let reader = BufReader::with_capacity(1, &buf[..]);
-        assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß');
-    }
-
-    #[test]
-    #[allow(deprecated)]
-    fn test_chars() {
-        let buf = [195, 159, b'a'];
-        let reader = BufReader::with_capacity(1, &buf[..]);
-        let mut it = reader.chars();
-        assert_eq!(it.next().unwrap().unwrap(), 'ß');
-        assert_eq!(it.next().unwrap().unwrap(), 'a');
-        assert!(it.next().is_none());
-    }
-
     #[test]
     #[should_panic]
     fn dont_panic_in_drop_on_panicked_flush() {
index 3622df16b9d0bd46020d49e97dabdb40d6214f0e..14f20151dca861c9ef6e3518392fdac9b4e49ce1 100644 (file)
@@ -550,26 +550,6 @@ fn test_buf_reader() {
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
-    #[test]
-    #[allow(deprecated)]
-    fn test_read_char() {
-        let b = &b"Vi\xE1\xBB\x87t"[..];
-        let mut c = Cursor::new(b).chars();
-        assert_eq!(c.next().unwrap().unwrap(), 'V');
-        assert_eq!(c.next().unwrap().unwrap(), 'i');
-        assert_eq!(c.next().unwrap().unwrap(), 'ệ');
-        assert_eq!(c.next().unwrap().unwrap(), 't');
-        assert!(c.next().is_none());
-    }
-
-    #[test]
-    #[allow(deprecated)]
-    fn test_read_bad_char() {
-        let b = &b"\x80"[..];
-        let mut c = Cursor::new(b).chars();
-        assert!(c.next().unwrap().is_err());
-    }
-
     #[test]
     fn seek_past_end() {
         let buf = [0xff];
index 8530487484827e5d8d404151a26bcb769eecde4c..b83f3fbe7a59cd94673791f7d3af7ec2bd3836fe 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use cmp;
-use core::str as core_str;
-use error as std_error;
 use fmt;
-use result;
 use str;
 use memchr;
 use ptr;
@@ -357,19 +354,26 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
 // avoid paying to allocate and zero a huge chunk of memory if the reader only
 // has 4 bytes while still making large reads if the reader does have a ton
 // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
-// time is 4,500 times (!) slower than this if the reader has a very small
-// amount of data to return.
+// time is 4,500 times (!) slower than a default reservation size of 32 if the
+// reader has a very small amount of data to return.
 //
 // Because we're extending the buffer with uninitialized data for trusted
 // readers, we need to make sure to truncate that if any of this panics.
 fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
+    read_to_end_with_reservation(r, buf, 32)
+}
+
+fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
+                                                  buf: &mut Vec<u8>,
+                                                  reservation_size: usize) -> Result<usize>
+{
     let start_len = buf.len();
     let mut g = Guard { len: buf.len(), buf: buf };
     let ret;
     loop {
         if g.len == g.buf.len() {
             unsafe {
-                g.buf.reserve(32);
+                g.buf.reserve(reservation_size);
                 let capacity = g.buf.capacity();
                 g.buf.set_len(capacity);
                 r.initializer().initialize(&mut g.buf[g.len..]);
@@ -800,53 +804,6 @@ fn bytes(self) -> Bytes<Self> where Self: Sized {
         Bytes { inner: self }
     }
 
-    /// Transforms this `Read` instance to an [`Iterator`] over [`char`]s.
-    ///
-    /// This adaptor will attempt to interpret this reader as a UTF-8 encoded
-    /// sequence of characters. The returned iterator will return [`None`] once
-    /// EOF is reached for this reader. Otherwise each element yielded will be a
-    /// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error
-    /// occurred or where decoding failed.
-    ///
-    /// Currently this adaptor will discard intermediate data read, and should
-    /// be avoided if this is not desired.
-    ///
-    /// # Examples
-    ///
-    /// [`File`]s implement `Read`:
-    ///
-    /// [`File`]: ../fs/struct.File.html
-    /// [`Iterator`]: ../../std/iter/trait.Iterator.html
-    /// [`Result`]: ../../std/result/enum.Result.html
-    /// [`char`]: ../../std/primitive.char.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// ```no_run
-    /// #![feature(io)]
-    /// use std::io;
-    /// use std::io::prelude::*;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> io::Result<()> {
-    ///     let mut f = File::open("foo.txt")?;
-    ///
-    ///     for c in f.chars() {
-    ///         println!("{}", c.unwrap());
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[unstable(feature = "io", reason = "the semantics of a partial read/write \
-                                         of where errors happen is currently \
-                                         unclear and may change",
-               issue = "27802")]
-    #[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-        https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-    #[allow(deprecated)]
-    fn chars(self) -> Chars<Self> where Self: Sized {
-        Chars { inner: self }
-    }
-
     /// Creates an adaptor which will chain this stream with another.
     ///
     /// The returned `Read` instance will first read all bytes from this object
@@ -1949,6 +1906,12 @@ fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
     unsafe fn initializer(&self) -> Initializer {
         self.inner.initializer()
     }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        let reservation_size = cmp::min(self.limit, 32) as usize;
+
+        read_to_end_with_reservation(self, buf, reservation_size)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2005,104 +1968,6 @@ fn next(&mut self) -> Option<Result<u8>> {
     }
 }
 
-/// An iterator over the `char`s of a reader.
-///
-/// This struct is generally created by calling [`chars`][chars] on a reader.
-/// Please see the documentation of `chars()` for more details.
-///
-/// [chars]: trait.Read.html#method.chars
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[derive(Debug)]
-#[allow(deprecated)]
-pub struct Chars<R> {
-    inner: R,
-}
-
-/// An enumeration of possible errors that can be generated from the `Chars`
-/// adapter.
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[derive(Debug)]
-#[allow(deprecated)]
-pub enum CharsError {
-    /// Variant representing that the underlying stream was read successfully
-    /// but it did not contain valid utf8 data.
-    NotUtf8,
-
-    /// Variant representing that an I/O error occurred.
-    Other(Error),
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[allow(deprecated)]
-impl<R: Read> Iterator for Chars<R> {
-    type Item = result::Result<char, CharsError>;
-
-    fn next(&mut self) -> Option<result::Result<char, CharsError>> {
-        let first_byte = match read_one_byte(&mut self.inner)? {
-            Ok(b) => b,
-            Err(e) => return Some(Err(CharsError::Other(e))),
-        };
-        let width = core_str::utf8_char_width(first_byte);
-        if width == 1 { return Some(Ok(first_byte as char)) }
-        if width == 0 { return Some(Err(CharsError::NotUtf8)) }
-        let mut buf = [first_byte, 0, 0, 0];
-        {
-            let mut start = 1;
-            while start < width {
-                match self.inner.read(&mut buf[start..width]) {
-                    Ok(0) => return Some(Err(CharsError::NotUtf8)),
-                    Ok(n) => start += n,
-                    Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
-                    Err(e) => return Some(Err(CharsError::Other(e))),
-                }
-            }
-        }
-        Some(match str::from_utf8(&buf[..width]).ok() {
-            Some(s) => Ok(s.chars().next().unwrap()),
-            None => Err(CharsError::NotUtf8),
-        })
-    }
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[allow(deprecated)]
-impl std_error::Error for CharsError {
-    fn description(&self) -> &str {
-        match *self {
-            CharsError::NotUtf8 => "invalid utf8 encoding",
-            CharsError::Other(ref e) => std_error::Error::description(e),
-        }
-    }
-    fn cause(&self) -> Option<&dyn std_error::Error> {
-        match *self {
-            CharsError::NotUtf8 => None,
-            CharsError::Other(ref e) => e.cause(),
-        }
-    }
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[allow(deprecated)]
-impl fmt::Display for CharsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            CharsError::NotUtf8 => {
-                "byte stream did not contain valid utf8".fmt(f)
-            }
-            CharsError::Other(ref e) => e.fmt(f),
-        }
-    }
-}
-
 /// An iterator over the contents of an instance of `BufRead` split on a
 /// particular byte.
 ///
index 0025f21da22a887cca799674c555d61e6c1608ad..f15494c5fd7f59beeab250014135eeb81f1ef5da 100644 (file)
@@ -157,12 +157,7 @@ macro_rules! print {
 macro_rules! println {
     () => (print!("\n"));
     ($($arg:tt)*) => ({
-        #[cfg(not(stage0))] {
-            ($crate::io::_print(format_args_nl!($($arg)*)));
-        }
-        #[cfg(stage0)] {
-            print!("{}\n", format_args!($($arg)*))
-        }
+        $crate::io::_print(format_args_nl!($($arg)*));
     })
 }
 
@@ -221,12 +216,7 @@ macro_rules! eprint {
 macro_rules! eprintln {
     () => (eprint!("\n"));
     ($($arg:tt)*) => ({
-        #[cfg(all(not(stage0), not(stage1)))] {
-            ($crate::io::_eprint(format_args_nl!($($arg)*)));
-        }
-        #[cfg(any(stage0, stage1))] {
-            eprint!("{}\n", format_args!($($arg)*))
-        }
+        $crate::io::_eprint(format_args_nl!($($arg)*));
     })
 }
 
@@ -237,14 +227,17 @@ macro_rules! eprintln {
 macro_rules! await {
     ($e:expr) => { {
         let mut pinned = $e;
-        let mut pinned = unsafe { $crate::mem::PinMut::new_unchecked(&mut pinned) };
         loop {
-            match $crate::future::poll_in_task_cx(&mut pinned) {
-                // FIXME(cramertj) prior to stabilizing await, we have to ensure that this
-                // can't be used to create a generator on stable via `|| await!()`.
-                $crate::task::Poll::Pending => yield,
-                $crate::task::Poll::Ready(x) => break x,
+            if let $crate::task::Poll::Ready(x) =
+                $crate::future::poll_in_task_cx(unsafe {
+                    $crate::mem::PinMut::new_unchecked(&mut pinned)
+                })
+            {
+                break x;
             }
+            // FIXME(cramertj) prior to stabilizing await, we have to ensure that this
+            // can't be used to create a generator on stable via `|| await!()`.
+            yield
         }
     } }
 }
diff --git a/src/libstd/os/hermit/fs.rs b/src/libstd/os/hermit/fs.rs
new file mode 100644 (file)
index 0000000..d2e7516
--- /dev/null
@@ -0,0 +1,389 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use libc;
+
+use fs::Metadata;
+use sys_common::AsInner;
+
+#[allow(deprecated)]
+use os::hermit::raw;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    /// Gain a reference to the underlying `stat` structure which contains
+    /// the raw information returned by the OS.
+    ///
+    /// The contents of the returned [`stat`] are **not** consistent across
+    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
+    /// cross-Unix abstractions contained within the raw stat.
+    ///
+    /// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let stat = meta.as_raw_stat();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    #[rustc_deprecated(since = "1.8.0",
+                       reason = "deprecated in favor of the accessor \
+                                 methods of this trait")]
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat;
+
+    /// Returns the device ID on which this file resides.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_dev());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    /// Returns the inode number.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_ino());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    /// Returns the file type and mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_mode());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    /// Returns the number of hard links to file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_nlink());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    /// Returns the user ID of the file owner.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_uid());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    /// Returns the group ID of the file owner.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_gid());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    /// Returns the device ID that this file represents. Only relevant for special file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_rdev());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
+    ///
+    /// The size of a symbolic link is the length of the pathname it contains,
+    /// without a terminating null byte.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_size());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    /// Returns the last access time.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_atime());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    /// Returns the last access time, nano seconds part.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_atime_nsec());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    /// Returns the last modification time.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_mtime());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    /// Returns the last modification time, nano seconds part.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_mtime_nsec());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    /// Returns the last status change time.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_ctime());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    /// Returns the last status change time, nano seconds part.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_ctime_nsec());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    /// Returns the "preferred" blocksize for efficient filesystem I/O.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_blksize());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    /// Returns the number of blocks allocated to the file, 512-byte units.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_blocks());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat {
+        unsafe {
+            &*(self.as_inner().as_inner() as *const libc::stat64
+                                          as *const raw::stat)
+        }
+    }
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atime as i64
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atime_nsec as i64
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime as i64
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime_nsec as i64
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime as i64
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime_nsec as i64
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+}
diff --git a/src/libstd/os/hermit/mod.rs b/src/libstd/os/hermit/mod.rs
new file mode 100644 (file)
index 0000000..fcb22cd
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! HermitCore-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod raw;
+pub mod fs;
diff --git a/src/libstd/os/hermit/raw.rs b/src/libstd/os/hermit/raw.rs
new file mode 100644 (file)
index 0000000..282afe0
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! HermitCore-specific raw type definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![rustc_deprecated(since = "1.8.0",
+                    reason = "these type aliases are no longer supported by \
+                              the standard library, the `libc` crate on \
+                              crates.io should be used instead for the correct \
+                              definitions")]
+#![allow(deprecated)]
+#![allow(missing_debug_implementations)]
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub use libc::pthread_t;
+
+#[doc(inline)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub use libc::{dev_t, mode_t, off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
index ac7809451d152d244a8d55df0a92cc46d697113b..c384ec9168ac4428889fd2ea5df4760f3f1ddd65 100644 (file)
@@ -47,6 +47,7 @@
         #[cfg(target_os = "solaris")]    pub mod solaris;
         #[cfg(target_os = "emscripten")] pub mod emscripten;
         #[cfg(target_os = "fuchsia")]    pub mod fuchsia;
+        #[cfg(target_os = "hermit")]     pub mod hermit;
 
         #[cfg(any(target_os = "redox", unix))]
         #[stable(feature = "rust1", since = "1.0.0")]
index 10282ecb6588370d35aabf305e49173508d6f12d..3abc260b4586878b8d17b139e1a2e8387c2d20e1 100644 (file)
@@ -178,6 +178,10 @@ pub const fn new() -> Once {
     /// happens-before relation between the closure and code executing after the
     /// return).
     ///
+    /// If the given closure recusively invokes `call_once` on the same `Once`
+    /// instance the exact behavior is not specified, allowed outcomes are
+    /// a panic or a deadlock.
+    ///
     /// # Examples
     ///
     /// ```
index dc1dba6f2f9b713bece298a7a85e1419e5402ecc..7e32ec1347e9e7be99f48221c64a793d4e2f72ee 100644 (file)
@@ -66,7 +66,8 @@ fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
           target_os = "emscripten",
           target_os = "haiku",
           target_os = "l4re",
-          target_os = "fuchsia"))]
+          target_os = "fuchsia",
+          target_os = "hermit"))]
 mod imp {
     use os::unix::prelude::*;
     use ptr;
index 4f878d8ad1fa84beccfa75343d1bc5872a0d8fd6..2007da7b1f6bec59b502a35fcf4cd2b80c9fbdf2 100644 (file)
@@ -41,13 +41,15 @@ pub const fn new() -> Condvar {
     #[cfg(any(target_os = "macos",
               target_os = "ios",
               target_os = "l4re",
-              target_os = "android"))]
+              target_os = "android",
+              target_os = "hermit"))]
     pub unsafe fn init(&mut self) {}
 
     #[cfg(not(any(target_os = "macos",
                   target_os = "ios",
                   target_os = "l4re",
-                  target_os = "android")))]
+                  target_os = "android",
+                  target_os = "hermit")))]
     pub unsafe fn init(&mut self) {
         use mem;
         let mut attr: libc::pthread_condattr_t = mem::uninitialized();
@@ -83,7 +85,10 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
     // where we configure condition variable to use monotonic clock (instead of
     // default system clock). This approach avoids all problems that result
     // from changes made to the system time.
-    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
+    #[cfg(not(any(target_os = "macos",
+                  target_os = "ios",
+                  target_os = "android",
+                  target_os = "hermit")))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         use mem;
 
@@ -113,7 +118,7 @@ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
     // This implementation is modeled after libcxx's condition_variable
     // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
     // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
         use ptr;
         use time::Instant;
index 00cf7eca75dc3eaf8148896027e938d621fd85a4..ad116c57f557e1c73fe8ae440073d2641d671fa7 100644 (file)
@@ -172,3 +172,14 @@ pub mod os {
     pub const EXE_SUFFIX: &'static str = "";
     pub const EXE_EXTENSION: &'static str = "";
 }
+
+#[cfg(target_os = "hermit")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "hermit";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
index d59d800a579474b5c320eb40be2003737530fab2..c13a0fea1e05c8f09b1aa29956f28d7d1dcc5b61 100644 (file)
@@ -20,7 +20,7 @@
 // fallback implementation to use as well.
 //
 // Due to rust-lang/rust#18804, make sure this is not generic!
-#[cfg(any(target_os = "linux", target_os = "fuchsia"))]
+#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
     use libc;
     use mem;
index 662a76d6725a68d7bb3493c7229330d446e1dd80..7a89d9857bbcf341c95c3a8955b82933e6c26560 100644 (file)
@@ -325,12 +325,12 @@ pub fn metadata(&self) -> io::Result<FileAttr> {
         lstat(&self.path())
     }
 
-    #[cfg(any(target_os = "solaris", target_os = "haiku"))]
+    #[cfg(any(target_os = "solaris", target_os = "haiku", target_os = "hermit"))]
     pub fn file_type(&self) -> io::Result<FileType> {
         lstat(&self.path()).map(|m| m.file_type())
     }
 
-    #[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
+    #[cfg(not(any(target_os = "solaris", target_os = "haiku", target_os = "hermit")))]
     pub fn file_type(&self) -> io::Result<FileType> {
         match self.entry.d_type {
             libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@@ -352,7 +352,8 @@ pub fn file_type(&self) -> io::Result<FileType> {
               target_os = "solaris",
               target_os = "haiku",
               target_os = "l4re",
-              target_os = "fuchsia"))]
+              target_os = "fuchsia",
+              target_os = "hermit"))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
     }
@@ -383,7 +384,8 @@ fn name_bytes(&self) -> &[u8] {
               target_os = "linux",
               target_os = "emscripten",
               target_os = "l4re",
-              target_os = "haiku"))]
+              target_os = "haiku",
+              target_os = "hermit"))]
     fn name_bytes(&self) -> &[u8] {
         unsafe {
             CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
index c1298e5040dbeec35b3a503c17d1aa2e4aa961c8..c738003caf1d9b220a980c1006b79f7ce6eeeb5d 100644 (file)
@@ -28,6 +28,7 @@
 #[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform;
 #[cfg(all(not(dox), target_os = "fuchsia"))]   pub use os::fuchsia as platform;
 #[cfg(all(not(dox), target_os = "l4re"))]      pub use os::linux as platform;
+#[cfg(all(not(dox), target_os = "hermit"))]    pub use os::hermit as platform;
 
 pub use self::rand::hashmap_random_keys;
 pub use libc::strlen;
index addf555eb106564fa357e67b19d85ea46d29d157..1d92e8fc97c7aa5690389bc17a75f5f942f75ebb 100644 (file)
@@ -47,6 +47,7 @@
                    target_os = "netbsd",
                    target_os = "openbsd",
                    target_os = "android",
+                   target_os = "hermit",
                    target_env = "newlib"),
                link_name = "__errno")]
     #[cfg_attr(target_os = "solaris", link_name = "___errno")]
@@ -376,7 +377,7 @@ fn _get_next_image_info(team_id: i32, cookie: *mut i32,
     }
 }
 
-#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
+#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     use io::ErrorKind;
     Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
index e26306c045d310aa6b9cd99d685ed6b1c6594623..f3a45d24657399dd33cdd564bc1b09c95f0c1dfc 100644 (file)
@@ -138,7 +138,8 @@ pub fn set_name(name: &CStr) {
               target_os = "solaris",
               target_os = "haiku",
               target_os = "l4re",
-              target_os = "emscripten"))]
+              target_os = "emscripten",
+              target_os = "hermit"))]
     pub fn set_name(_name: &CStr) {
         // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
     }
index 89786eb2a6c486005c27ba46da3375fa3fd79aa7..0b1fb726357e1056d8685ce50e338843d842c5a8 100644 (file)
@@ -345,9 +345,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         }
     }
 
-    #[cfg(not(target_os = "dragonfly"))]
+    #[cfg(not(any(target_os = "dragonfly", target_os = "hermit")))]
     pub type clock_t = libc::c_int;
-    #[cfg(target_os = "dragonfly")]
+    #[cfg(any(target_os = "dragonfly", target_os = "hermit"))]
     pub type clock_t = libc::c_ulong;
 
     fn now(clock: clock_t) -> Timespec {
index 30aba2f400f2f8059fd6680105833d5f0d77d827..6f81afe66f95b694ae1123d9da74bfd501103a43 100644 (file)
@@ -296,6 +296,8 @@ pub struct ipv6_mreq {
 
 pub const FD_SETSIZE: usize = 64;
 
+pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
+
 #[repr(C)]
 #[cfg(not(target_pointer_width = "64"))]
 pub struct WSADATA {
index 44ec872b2446b956d85677a5e5d28f60a4a2bc44..85588cc6c8e85e074e3d3d52c085a9defbb46a16 100644 (file)
@@ -42,7 +42,8 @@ pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
         let stack_size = (stack + 0xfffe) & (!0xfffe);
         let ret = c::CreateThread(ptr::null_mut(), stack_size,
                                   thread_start, &*p as *const _ as *mut _,
-                                  0, ptr::null_mut());
+                                  c::STACK_SIZE_PARAM_IS_A_RESERVATION,
+                                  ptr::null_mut());
 
         return if ret as usize == 0 {
             Err(io::Error::last_os_error())
index ae804ad409ee311fdbb73b7b582cd9b2176b1974..bbe80df7e8bdbc54cfc7d132af0d485304440d90 100644 (file)
@@ -731,7 +731,8 @@ pub fn sleep(dur: Duration) {
 ///   specifying a maximum time to block the thread for.
 ///
 /// * The [`unpark`] method on a [`Thread`] atomically makes the token available
-///   if it wasn't already.
+///   if it wasn't already. Because the token is initially absent, [`unpark`]
+///   followed by [`park`] will result in the second call returning immediately.
 ///
 /// In other words, each [`Thread`] acts a bit like a spinlock that can be
 /// locked and unlocked using `park` and `unpark`.
@@ -766,6 +767,8 @@ pub fn sleep(dur: Duration) {
 /// // Let some time pass for the thread to be spawned.
 /// thread::sleep(Duration::from_millis(10));
 ///
+/// // There is no race condition here, if `unpark`
+/// // happens first, `park` will return immediately.
 /// println!("Unpark the thread");
 /// parked_thread.thread().unpark();
 ///
diff --git a/src/libstd_unicode/Cargo.toml b/src/libstd_unicode/Cargo.toml
deleted file mode 100644 (file)
index b1c55c2..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "std_unicode"
-version = "0.0.0"
-
-[lib]
-name = "std_unicode"
-path = "lib.rs"
-test = false
-bench = false
-
-[dependencies]
-core = { path = "../libcore" }
-compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
deleted file mode 100644 (file)
index c0d47f1..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! # The Unicode Library
-//!
-//! Unicode-intensive functions for `char` and `str` types.
-//!
-//! This crate provides a collection of Unicode-related functionality,
-//! including decompositions, conversions, etc., and provides traits
-//! implementing these functions for the `char` and `str` types.
-//!
-//! The functionality included here is only that which is necessary to
-//! provide for basic string-related manipulations. This crate does not
-//! (yet) aim to provide a full set of Unicode tables.
-
-#![unstable(feature = "unicode", issue = "27783")]
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-       html_root_url = "https://doc.rust-lang.org/nightly/",
-       html_playground_url = "https://play.rust-lang.org/",
-       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
-       test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
-#![no_std]
-
-#![feature(unicode_internals)]
-#![feature(staged_api)]
-#![rustc_deprecated(since = "1.27.0", reason = "moved into libcore")]
-
-pub use core::unicode::*;
index d59c9dd6b53e8fbc5399984ec1d81a0ec40ae4d6..28c1e4324de7a3070c90f2c4cce5a694dc3ce2e8 100644 (file)
@@ -23,6 +23,7 @@
 use print::pprust;
 use ptr::P;
 use rustc_data_structures::indexed_vec;
+use rustc_data_structures::indexed_vec::Idx;
 use symbol::{Symbol, keywords};
 use tokenstream::{ThinTokenStream, TokenStream};
 
@@ -1910,9 +1911,18 @@ pub enum AttrStyle {
     Inner,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialOrd, Ord, Copy)]
 pub struct AttrId(pub usize);
 
+impl Idx for AttrId {
+    fn new(idx: usize) -> Self {
+        AttrId(idx)
+    }
+    fn index(self) -> usize {
+        self.0
+    }
+}
+
 /// Meta-data associated with an item
 /// Doc-comments are promoted to attributes that have is_sugared_doc = true
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
index 137b94230a3cd251ccdb9864499de835daaa15c7..b3b173db70b8906649f300f7cbdc9060abfad849 100644 (file)
 
 pub fn mark_used(attr: &Attribute) {
     debug!("Marking {:?} as used.", attr);
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let mut slot = globals.used_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        if slot.len() <= idx {
-            slot.resize(idx + 1, 0);
-        }
-        slot[idx] |= 1 << shift;
+        globals.used_attrs.lock().insert(attr.id);
     });
 }
 
 pub fn is_used(attr: &Attribute) -> bool {
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let slot = globals.used_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        slot.get(idx).map(|bits| bits & (1 << shift) != 0)
-            .unwrap_or(false)
+        globals.used_attrs.lock().contains(attr.id)
     })
 }
 
 pub fn mark_known(attr: &Attribute) {
     debug!("Marking {:?} as known.", attr);
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let mut slot = globals.known_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        if slot.len() <= idx {
-            slot.resize(idx + 1, 0);
-        }
-        slot[idx] |= 1 << shift;
+        globals.known_attrs.lock().insert(attr.id);
     });
 }
 
 pub fn is_known(attr: &Attribute) -> bool {
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let slot = globals.known_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        slot.get(idx).map(|bits| bits & (1 << shift) != 0)
-            .unwrap_or(false)
+        globals.known_attrs.lock().contains(attr.id)
     })
 }
 
-const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
-const RUST_KNOWN_LINT_TOOL: &[&str] = &["clippy"];
-
-pub fn is_known_tool(attr: &Attribute) -> bool {
-    let tool_name =
-        attr.path.segments.iter().next().expect("empty path in attribute").ident.name;
-    RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref())
-}
-
 pub fn is_known_lint_tool(m_item: Ident) -> bool {
-    RUST_KNOWN_LINT_TOOL.contains(&m_item.as_str().as_ref())
+    ["clippy"].contains(&m_item.as_str().as_ref())
 }
 
 impl NestedMetaItem {
@@ -245,10 +212,6 @@ pub fn is_meta_item_list(&self) -> bool {
     pub fn is_value_str(&self) -> bool {
         self.value_str().is_some()
     }
-
-    pub fn is_scoped(&self) -> bool {
-        self.path.segments.len() > 1
-    }
 }
 
 impl MetaItem {
index b55c4f99206c4204858092501e30d0c39d6e579e..8450daa3f7c943fc93dc1de90f9f97730c8aaa2a 100644 (file)
@@ -588,6 +588,9 @@ pub fn descr(self) -> &'static str {
 
 /// An enum representing the different kinds of syntax extensions.
 pub enum SyntaxExtension {
+    /// A trivial "extension" that does nothing, only keeps the attribute and marks it as known.
+    NonMacroAttr,
+
     /// A syntax extension that is attached to an item and creates new items
     /// based upon it.
     ///
@@ -667,6 +670,7 @@ pub fn kind(&self) -> MacroKind {
             SyntaxExtension::IdentTT(..) |
             SyntaxExtension::ProcMacro { .. } =>
                 MacroKind::Bang,
+            SyntaxExtension::NonMacroAttr |
             SyntaxExtension::MultiDecorator(..) |
             SyntaxExtension::MultiModifier(..) |
             SyntaxExtension::AttrProcMacro(..) =>
@@ -696,6 +700,7 @@ pub fn edition(&self) -> Edition {
             SyntaxExtension::AttrProcMacro(.., edition) |
             SyntaxExtension::ProcMacroDerive(.., edition) => edition,
             // Unstable legacy stuff
+            SyntaxExtension::NonMacroAttr |
             SyntaxExtension::IdentTT(..) |
             SyntaxExtension::MultiDecorator(..) |
             SyntaxExtension::MultiModifier(..) |
index 9f8909e16264e601b6b2ba7184820715e75d0e8b..8bd30e434767be5a3397e1cf8c78ffd9450e2a64 100644 (file)
@@ -15,6 +15,7 @@
 use config::{is_test_or_bench, StripUnconfigured};
 use errors::{Applicability, FatalError};
 use ext::base::*;
+use ext::build::AstBuilder;
 use ext::derive::{add_derived_markers, collect_derives};
 use ext::hygiene::{self, Mark, SyntaxContext};
 use ext::placeholders::{placeholder, PlaceholderExpander};
@@ -36,7 +37,7 @@
 use std::collections::HashMap;
 use std::fs::File;
 use std::io::Read;
-use std::mem;
+use std::{iter, mem};
 use std::rc::Rc;
 use std::path::PathBuf;
 
@@ -243,6 +244,15 @@ pub fn span(&self) -> Span {
         }
     }
 
+    pub fn path_span(&self) -> Span {
+        match self.kind {
+            InvocationKind::Bang { ref mac, .. } => mac.node.path.span,
+            InvocationKind::Attr { attr: Some(ref attr), .. } => attr.path.span,
+            InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
+            InvocationKind::Derive { ref path, .. } => path.span,
+        }
+    }
+
     pub fn attr_id(&self) -> Option<ast::AttrId> {
         match self.kind {
             InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id),
@@ -474,6 +484,7 @@ fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
                 cx: self.cx,
                 invocations: Vec::new(),
                 monotonic: self.monotonic,
+                tests_nameable: true,
             };
             (fragment.fold_with(&mut collector), collector.invocations)
         };
@@ -566,6 +577,11 @@ fn expand_attr_invoc(&mut self,
         });
 
         match *ext {
+            NonMacroAttr => {
+                attr::mark_known(&attr);
+                let item = item.map_attrs(|mut attrs| { attrs.push(attr); attrs });
+                Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
+            }
             MultiModifier(ref mac) => {
                 let meta = attr.parse_meta(self.cx.parse_sess)
                                .map_err(|mut e| { e.emit(); }).ok()?;
@@ -810,7 +826,8 @@ fn expand_bang_invoc(&mut self,
                 }
             }
 
-            MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
+            MultiDecorator(..) | MultiModifier(..) |
+            AttrProcMacro(..) | SyntaxExtension::NonMacroAttr => {
                 self.cx.span_err(path.span,
                                  &format!("`{}` can only be used in attributes", path));
                 self.cx.trace_macros_diag();
@@ -1049,6 +1066,11 @@ struct InvocationCollector<'a, 'b: 'a> {
     cfg: StripUnconfigured<'a>,
     invocations: Vec<Invocation>,
     monotonic: bool,
+
+    /// Test functions need to be nameable. Tests inside functions or in other
+    /// unnameable locations need to be ignored. `tests_nameable` tracks whether
+    /// any test functions found in the current context would be nameable.
+    tests_nameable: bool,
 }
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
@@ -1066,6 +1088,20 @@ fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> A
         placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
     }
 
+    /// Folds the item allowing tests to be expanded because they are still nameable.
+    /// This should probably only be called with module items
+    fn fold_nameable(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+        fold::noop_fold_item(item, self)
+    }
+
+    /// Folds the item but doesn't allow tests to occur within it
+    fn fold_unnameable(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+        let was_nameable = mem::replace(&mut self.tests_nameable, false);
+        let items = fold::noop_fold_item(item, self);
+        self.tests_nameable = was_nameable;
+        items
+    }
+
     fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
         self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
     }
@@ -1306,7 +1342,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
             }
             ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
                 if item.ident == keywords::Invalid.ident() {
-                    return noop_fold_item(item, self);
+                    return self.fold_nameable(item);
                 }
 
                 let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
@@ -1346,22 +1382,58 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
 
                 let orig_module =
                     mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
-                let result = noop_fold_item(item, self);
+                let result = self.fold_nameable(item);
                 self.cx.current_expansion.module = orig_module;
                 self.cx.current_expansion.directory_ownership = orig_directory_ownership;
                 result
             }
             // Ensure that test functions are accessible from the test harness.
+            // #[test] fn foo() {}
+            // becomes:
+            // #[test] pub fn foo_gensym(){}
+            // #[allow(unused)]
+            // use foo_gensym as foo;
             ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
-                if item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
+                if self.tests_nameable && item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
+                    let orig_ident = item.ident;
+                    let orig_vis   = item.vis.clone();
+
+                    // Publicize the item under gensymed name to avoid pollution
                     item = item.map(|mut item| {
                         item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
+                        item.ident = item.ident.gensym();
                         item
                     });
+
+                    // Use the gensymed name under the item's original visibility
+                    let mut use_item = self.cx.item_use_simple_(
+                        item.ident.span,
+                        orig_vis,
+                        Some(orig_ident),
+                        self.cx.path(item.ident.span,
+                            vec![keywords::SelfValue.ident(), item.ident]));
+
+                    // #[allow(unused)] because the test function probably isn't being referenced
+                    use_item = use_item.map(|mut ui| {
+                        ui.attrs.push(
+                            self.cx.attribute(DUMMY_SP, attr::mk_list_item(DUMMY_SP,
+                                Ident::from_str("allow"), vec![
+                                    attr::mk_nested_word_item(Ident::from_str("unused"))
+                                ]
+                            ))
+                        );
+
+                        ui
+                    });
+
+                    SmallVector::many(
+                        self.fold_unnameable(item).into_iter()
+                            .chain(self.fold_unnameable(use_item)))
+                } else {
+                    self.fold_unnameable(item)
                 }
-                noop_fold_item(item, self)
             }
-            _ => noop_fold_item(item, self),
+            _ => self.fold_unnameable(item),
         }
     }
 
@@ -1612,13 +1684,16 @@ fn enable_trace_macros = trace_macros,
         fn enable_allow_internal_unstable = allow_internal_unstable,
         fn enable_custom_derive = custom_derive,
         fn enable_format_args_nl = format_args_nl,
-        fn use_extern_macros_enabled = use_extern_macros,
         fn macros_in_extern_enabled = macros_in_extern,
         fn proc_macro_mod = proc_macro_mod,
         fn proc_macro_gen = proc_macro_gen,
         fn proc_macro_expr = proc_macro_expr,
         fn proc_macro_non_items = proc_macro_non_items,
     }
+
+    pub fn use_extern_macros_enabled(&self) -> bool {
+        self.features.map_or(false, |features| features.use_extern_macros())
+    }
 }
 
 // A Marker adds the given mark to the syntax context.
index 40fb2c69e57cb3d24bfdf54c1703ca6b70094a1c..77e3faa5b1faca25b7d386c1e0f44eb394009626 100644 (file)
@@ -80,6 +80,11 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
             {
                 $(f(stringify!($feature), self.$feature);)+
             }
+
+            pub fn use_extern_macros(&self) -> bool {
+                // The `decl_macro` and `tool_attributes` features imply `use_extern_macros`.
+                self.use_extern_macros || self.decl_macro || self.tool_attributes
+            }
         }
     };
 
@@ -396,7 +401,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Infer outlives requirements; RFC 2093
     (active, infer_outlives_requirements, "1.26.0", Some(44493), None),
 
-    // Infer outlives requirements; RFC 2093
+    // Infer static outlives requirements; RFC 2093
     (active, infer_static_outlives_requirements, "1.26.0", Some(44493), None),
 
     // Multiple patterns with `|` in `if let` and `while let`
@@ -689,6 +694,10 @@ pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, Att
     BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
 }
 
+pub fn is_builtin_attr_name(name: ast::Name) -> bool {
+    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| name == builtin_name)
+}
+
 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name)) ||
     attr.name().as_str().starts_with("rustc_")
@@ -1198,28 +1207,9 @@ fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
             // before the plugin attributes are registered
             // so we skip this then
             if !is_macro {
-                if attr.is_scoped() {
-                    gate_feature!(self, tool_attributes, attr.span,
-                                  &format!("scoped attribute `{}` is experimental", attr.path));
-                    if attr::is_known_tool(attr) {
-                        attr::mark_used(attr);
-                    } else {
-                        span_err!(
-                            self.parse_sess.span_diagnostic,
-                            attr.span,
-                            E0694,
-                            "an unknown tool name found in scoped attribute: `{}`.",
-                            attr.path
-                        );
-                    }
-                } else {
-                    gate_feature!(self, custom_attribute, attr.span,
-                                  &format!("The attribute `{}` is currently \
-                                            unknown to the compiler and \
-                                            may have meaning \
-                                            added to it in the future",
-                                           attr.path));
-                }
+                let msg = format!("The attribute `{}` is currently unknown to the compiler and \
+                                   may have meaning added to it in the future", attr.path);
+                gate_feature!(self, custom_attribute, attr.span, &msg);
             }
         }
     }
@@ -1529,7 +1519,7 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
             }
         }
 
-        if self.context.features.use_extern_macros && attr::is_known(attr) {
+        if self.context.features.use_extern_macros() && attr::is_known(attr) {
             return
         }
 
@@ -2004,7 +1994,7 @@ impl FeatureChecker {
     // the branching can be eliminated by modifying `set!()` to set these spans
     // only for the features that need to be checked for mutual exclusion.
     fn collect(&mut self, features: &Features, span: Span) {
-        if features.use_extern_macros {
+        if features.use_extern_macros() {
             // If self.use_extern_macros is None, set to Some(span)
             self.use_extern_macros = self.use_extern_macros.or(Some(span));
         }
index 60de94821bba0ba7b87a9a634ab74c36a4d5fa22..0c105865e0c2e13e3c916d8c1a7f0b9af7d55d8f 100644 (file)
@@ -43,6 +43,8 @@
 extern crate serialize as rustc_serialize; // used by deriving
 
 use rustc_data_structures::sync::Lock;
+use rustc_data_structures::bitvec::BitVector;
+use ast::AttrId;
 
 // A variant of 'try!' that panics on an Err. This is used as a crutch on the
 // way towards a non-panic!-prone parser. It should be used for fatal parsing
@@ -75,16 +77,18 @@ macro_rules! unwrap_or {
 }
 
 pub struct Globals {
-    used_attrs: Lock<Vec<u64>>,
-    known_attrs: Lock<Vec<u64>>,
+    used_attrs: Lock<BitVector<AttrId>>,
+    known_attrs: Lock<BitVector<AttrId>>,
     syntax_pos_globals: syntax_pos::Globals,
 }
 
 impl Globals {
     fn new() -> Globals {
         Globals {
-            used_attrs: Lock::new(Vec::new()),
-            known_attrs: Lock::new(Vec::new()),
+            // We have no idea how many attributes their will be, so just
+            // initiate the vectors with 0 bits. We'll grow them as necessary.
+            used_attrs: Lock::new(BitVector::new()),
+            known_attrs: Lock::new(BitVector::new()),
             syntax_pos_globals: syntax_pos::Globals::new(),
         }
     }
index fd8f394a600f09b456b97774f2a208d7b2783642..c449cc0a6525a9bdcb41136908f536706311a421 100644 (file)
@@ -104,6 +104,7 @@ pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
     !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
+        keywords::Async.name(),
         keywords::Do.name(),
         keywords::Box.name(),
         keywords::Break.name(),
index 23a37ca34853c6ad39586a3c2e26422038ca645e..6eba3c4f2bbc9c96e64daf43f1e68516dad911cd 100644 (file)
@@ -774,31 +774,41 @@ pub mod shell {
 
     #[derive(Clone, PartialEq, Debug)]
     pub enum Substitution<'a> {
-        Ordinal(u8),
-        Name(&'a str),
-        Escape,
+        Ordinal(u8, (usize, usize)),
+        Name(&'a str, (usize, usize)),
+        Escape((usize, usize)),
     }
 
     impl<'a> Substitution<'a> {
         pub fn as_str(&self) -> String {
-            match *self {
-                Substitution::Ordinal(n) => format!("${}", n),
-                Substitution::Name(n) => format!("${}", n),
-                Substitution::Escape => "$$".into(),
+            match self {
+                Substitution::Ordinal(n, _) => format!("${}", n),
+                Substitution::Name(n, _) => format!("${}", n),
+                Substitution::Escape(_) => "$$".into(),
             }
         }
 
         pub fn position(&self) -> Option<(usize, usize)> {
-            match *self {
-                _ => None,
+            match self {
+                Substitution::Ordinal(_, pos) |
+                Substitution::Name(_, pos) |
+                Substitution::Escape(pos) => Some(*pos),
+            }
+        }
+
+        pub fn set_position(&mut self, start: usize, end: usize) {
+            match self {
+                Substitution::Ordinal(_, ref mut pos) |
+                Substitution::Name(_, ref mut pos) |
+                Substitution::Escape(ref mut pos) => *pos = (start, end),
             }
         }
 
         pub fn translate(&self) -> Option<String> {
             match *self {
-                Substitution::Ordinal(n) => Some(format!("{{{}}}", n)),
-                Substitution::Name(n) => Some(format!("{{{}}}", n)),
-                Substitution::Escape => None,
+                Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)),
+                Substitution::Name(n, _) => Some(format!("{{{}}}", n)),
+                Substitution::Escape(_) => None,
             }
         }
     }
@@ -807,20 +817,26 @@ pub fn translate(&self) -> Option<String> {
     pub fn iter_subs(s: &str) -> Substitutions {
         Substitutions {
             s,
+            pos: 0,
         }
     }
 
     /// Iterator over substitutions in a string.
     pub struct Substitutions<'a> {
         s: &'a str,
+        pos: usize,
     }
 
     impl<'a> Iterator for Substitutions<'a> {
         type Item = Substitution<'a>;
         fn next(&mut self) -> Option<Self::Item> {
             match parse_next_substitution(self.s) {
-                Some((sub, tail)) => {
+                Some((mut sub, tail)) => {
                     self.s = tail;
+                    if let Some((start, end)) = sub.position() {
+                        sub.set_position(start + self.pos, end + self.pos);
+                        self.pos += end;
+                    }
                     Some(sub)
                 },
                 None => None,
@@ -837,15 +853,15 @@ pub fn parse_next_substitution(s: &str) -> Option<(Substitution, &str)> {
         let at = {
             let start = s.find('$')?;
             match s[start+1..].chars().next()? {
-                '$' => return Some((Substitution::Escape, &s[start+2..])),
+                '$' => return Some((Substitution::Escape((start, start+2)), &s[start+2..])),
                 c @ '0' ..= '9' => {
                     let n = (c as u8) - b'0';
-                    return Some((Substitution::Ordinal(n), &s[start+2..]));
+                    return Some((Substitution::Ordinal(n, (start, start+2)), &s[start+2..]));
                 },
                 _ => {/* fall-through */},
             }
 
-            Cur::new_at_start(&s[start..])
+            Cur::new_at(&s[..], start)
         };
 
         let at = at.at_next_cp()?;
@@ -855,7 +871,10 @@ pub fn parse_next_substitution(s: &str) -> Option<(Substitution, &str)> {
             None
         } else {
             let end = at_next_cp_while(inner, is_ident_tail);
-            Some((Substitution::Name(at.slice_between(end).unwrap()), end.slice_after()))
+            let slice = at.slice_between(end).unwrap();
+            let start = at.at - 1;
+            let end_pos = at.at + slice.len();
+            Some((Substitution::Name(slice, (start, end_pos)), end.slice_after()))
         }
     }
 
@@ -907,24 +926,24 @@ macro_rules! assert_eq_pnsat {
         fn test_escape() {
             assert_eq!(pns("has no escapes"), None);
             assert_eq!(pns("has no escapes, either $"), None);
-            assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape, " escape")));
-            assert_eq!(pns("$$ leading escape"), Some((S::Escape, " leading escape")));
-            assert_eq!(pns("trailing escape $$"), Some((S::Escape, "")));
+            assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape((11, 13)), " escape")));
+            assert_eq!(pns("$$ leading escape"), Some((S::Escape((0, 2)), " leading escape")));
+            assert_eq!(pns("trailing escape $$"), Some((S::Escape((16, 18)), "")));
         }
 
         #[test]
         fn test_parse() {
             macro_rules! assert_pns_eq_sub {
-                ($in_:expr, $kind:ident($arg:expr)) => {
-                    assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into()), "!")))
+                ($in_:expr, $kind:ident($arg:expr, $pos:expr)) => {
+                    assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into(), $pos), "!")))
                 };
             }
 
-            assert_pns_eq_sub!("$0", Ordinal(0));
-            assert_pns_eq_sub!("$1", Ordinal(1));
-            assert_pns_eq_sub!("$9", Ordinal(9));
-            assert_pns_eq_sub!("$N", Name("N"));
-            assert_pns_eq_sub!("$NAME", Name("NAME"));
+            assert_pns_eq_sub!("$0", Ordinal(0, (0, 2)));
+            assert_pns_eq_sub!("$1", Ordinal(1, (0, 2)));
+            assert_pns_eq_sub!("$9", Ordinal(9, (0, 2)));
+            assert_pns_eq_sub!("$N", Name("N", (0, 2)));
+            assert_pns_eq_sub!("$NAME", Name("NAME", (0, 5)));
         }
 
         #[test]
@@ -961,13 +980,6 @@ pub struct StrCursor<'a> {
     }
 
     impl<'a> StrCursor<'a> {
-        pub fn new_at_start(s: &'a str) -> StrCursor<'a> {
-            StrCursor {
-                s,
-                at: 0,
-            }
-        }
-
         pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> {
             StrCursor {
                 s,
index 1531f030127e302516fe924b350571ac3d5e3675..670fd5b872d92f96b5736378399c87333e14de0a 100644 (file)
@@ -594,7 +594,6 @@ pub fn name(&self) -> Symbol {
 /// The kind of compiler desugaring.
 #[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub enum CompilerDesugaringKind {
-    DotFill,
     QuestionMark,
     Catch,
     /// Desugaring of an `impl Trait` in return type position
@@ -609,7 +608,6 @@ impl CompilerDesugaringKind {
     pub fn name(self) -> Symbol {
         Symbol::intern(match self {
             CompilerDesugaringKind::Async => "async",
-            CompilerDesugaringKind::DotFill => "...",
             CompilerDesugaringKind::QuestionMark => "?",
             CompilerDesugaringKind::Catch => "do catch",
             CompilerDesugaringKind::ExistentialReturnType => "existential type",
index 03684905101f0b7e49dfe530e54dc1aeac6ef0fb..e19f07f5a6e5546ab4f6ea951e3c6b8627edeaa7 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 03684905101f0b7e49dfe530e54dc1aeac6ef0fb
+Subproject commit e19f07f5a6e5546ab4f6ea951e3c6b8627edeaa7
index 93157cd681942c5e51c0c44286f1b8d5764eec03..49a4962858ca733d0a65ddd8ad376a25798e1512 100644 (file)
@@ -148,7 +148,7 @@ LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) {
 #if LLVM_VERSION_GE(4, 0)
   Expected<StringRef> NameOrErr = Child->getName();
   if (!NameOrErr) {
-    // rustc_llvm currently doesn't use this error string, but it might be
+    // rustc_codegen_llvm currently doesn't use this error string, but it might be
     // useful in the future, and in the mean time this tells LLVM that the
     // error was not ignored and that it shouldn't abort the process.
     LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str());
index 85fbc4bf378a5358fe91d38ca7f4c5b52161f1da..7305dc71cbf63fa5bd14fc2b8d6e7edb74e4b832 100644 (file)
@@ -171,6 +171,12 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
 #define SUBTARGET_MSP430
 #endif
 
+#ifdef LLVM_COMPONENT_RISCV
+#define SUBTARGET_RISCV SUBTARGET(RISCV)
+#else
+#define SUBTARGET_RISCV
+#endif
+
 #ifdef LLVM_COMPONENT_SPARC
 #define SUBTARGET_SPARC SUBTARGET(Sparc)
 #else
@@ -192,7 +198,8 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
   SUBTARGET_SYSTEMZ                                                            \
   SUBTARGET_MSP430                                                             \
   SUBTARGET_SPARC                                                              \
-  SUBTARGET_HEXAGON
+  SUBTARGET_HEXAGON                                                            \
+  SUBTARGET_RISCV                                                              \
 
 #define SUBTARGET(x)                                                           \
   namespace llvm {                                                             \
@@ -828,23 +835,6 @@ LLVMRustPGOAvailable() {
 // and various online resources about ThinLTO to make heads or tails of all
 // this.
 
-extern "C" bool
-LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR,
-                               LLVMModuleRef M,
-                               const char *BcFile) {
-  llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
-  std::error_code EC;
-  llvm::raw_fd_ostream bc(BcFile, EC, llvm::sys::fs::F_None);
-  if (EC) {
-    LLVMRustSetLastError(EC.message().c_str());
-    return false;
-  }
-  PM->add(createWriteThinLTOBitcodePass(bc));
-  PM->run(*unwrap(M));
-  delete PM;
-  return true;
-}
-
 // This is a shared data structure which *must* be threadsafe to share
 // read-only amongst threads. This also corresponds basically to the arguments
 // of the `ProcessThinLTOModule` function in the LLVM source.
@@ -1092,7 +1082,7 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
     auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
 
     if (!MOrErr)
-      return std::move(MOrErr);
+      return MOrErr;
 
     // The rest of this closure is a workaround for
     // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
@@ -1110,14 +1100,14 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
     // shouldn't be a perf hit.
     if (Error Err = (*MOrErr)->materializeMetadata()) {
       Expected<std::unique_ptr<Module>> Ret(std::move(Err));
-      return std::move(Ret);
+      return Ret;
     }
 
     auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
     if (WasmCustomSections)
       WasmCustomSections->eraseFromParent();
 
-    return std::move(MOrErr);
+    return MOrErr;
   };
   FunctionImporter Importer(Data->Index, Loader);
   Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
@@ -1259,13 +1249,6 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
 
 #else
 
-extern "C" bool
-LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR,
-                               LLVMModuleRef M,
-                               const char *BcFile) {
-  report_fatal_error("ThinLTO not available");
-}
-
 struct LLVMRustThinLTOData {
 };
 
index d82410618d04ba6253744b67ee7a0cd54af59ec3..4bcb4fd7ad385a4ec1c0db8593a65cb578d248e6 100644 (file)
@@ -750,15 +750,6 @@ LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
                                DINodeArray(unwrapDI<MDTuple>(Subscripts))));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateVectorType(LLVMRustDIBuilderRef Builder, uint64_t Size,
-                                  uint32_t AlignInBits, LLVMMetadataRef Ty,
-                                  LLVMMetadataRef Subscripts) {
-  return wrap(
-      Builder->createVectorType(Size, AlignInBits, unwrapDI<DIType>(Ty),
-                                DINodeArray(unwrapDI<MDTuple>(Subscripts))));
-}
-
 extern "C" LLVMMetadataRef
 LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
                                      int64_t Count) {
@@ -993,6 +984,7 @@ enum class LLVMRustDiagnosticKind {
   OptimizationRemarkOther,
   OptimizationFailure,
   PGOProfile,
+  Linker,
 };
 
 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
@@ -1017,6 +1009,8 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
   case DK_PGOProfile:
     return LLVMRustDiagnosticKind::PGOProfile;
+  case DK_Linker:
+    return LLVMRustDiagnosticKind::Linker;
   default:
     return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
                ? LLVMRustDiagnosticKind::OptimizationRemarkOther
index 1722211c9e89f49f5c84c43da135479305481f12..7da830e1125bab2f7e2788ab8a4546d7b7584d05 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-07-12
\ No newline at end of file
+2018-08-02
index aa6339c852221ed7a37f75357c37323bb0ec8302..a93b25607eb3ad2ab9da4555750dd4bbd533a7f4 100644 (file)
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-07-27
+date: 2018-08-01
 rustc: beta
 cargo: beta
 
diff --git a/src/test/codegen/slice-position-bounds-check.rs b/src/test/codegen/slice-position-bounds-check.rs
new file mode 100644 (file)
index 0000000..a6c846d
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-system-llvm
+// compile-flags: -O -C panic=abort
+#![crate_type = "lib"]
+
+fn search<T: Ord + Eq>(arr: &mut [T], a: &T) -> Result<usize, ()> {
+    match arr.iter().position(|x| x == a) {
+        Some(p) => {
+            Ok(p)
+        },
+        None => Err(()),
+    }
+}
+
+// CHECK-LABEL: @position_no_bounds_check
+#[no_mangle]
+pub fn position_no_bounds_check(y: &mut [u32], x: &u32, z: &u32) -> bool {
+    // This contains "call assume" so we cannot just rule out all calls
+    // CHECK-NOT: panic_bounds_check
+    if let Ok(p) = search(y, x) {
+      y[p] == *z
+    } else {
+      false
+    }
+}
+
+// just to make sure that panicking really emits "panic_bounds_check" somewhere in the IR
+// CHECK-LABEL: @test_check
+#[no_mangle]
+pub fn test_check(y: &[i32]) -> i32 {
+    // CHECK: panic_bounds_check
+    y[12]
+}
index d3b7a5cd598825c441468d7c262a91c7f8c9764f..56c4364d598e75f45b50eeff6acf7556cb98606f 100644 (file)
@@ -11,6 +11,7 @@
 // Checks that we correctly codegen extern "C" functions returning structs.
 // See issue #52638.
 
+// only-sparc64
 // compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
 #![feature(no_core, lang_items)]
 #![no_core]
diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs
new file mode 100644 (file)
index 0000000..a73dd07
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @vec_clear
+#[no_mangle]
+pub fn vec_clear(x: &mut Vec<u32>) {
+    // CHECK-NOT: load
+    // CHECK-NOT: icmp
+    x.clear()
+}
diff --git a/src/test/compile-fail/auxiliary/issue-52489.rs b/src/test/compile-fail/auxiliary/issue-52489.rs
new file mode 100644 (file)
index 0000000..68d1ef8
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+#![unstable(feature = "issue_52489_unstable", issue = "0")]
+#![feature(staged_api)]
diff --git a/src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs b/src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs
new file mode 100644 (file)
index 0000000..ea09327
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs b/src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs
new file mode 100644 (file)
index 0000000..ea09327
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
index 09ebf1681c5e04540f1e2114ee38b26af06f68a4..10376d5780908d6ed1f16050b09d2823450f10f8 100644 (file)
@@ -16,7 +16,7 @@ union Foo {
 
 enum Bar {
     Boo = [unsafe { Foo { b: () }.a }; 4][3],
-    //~^ ERROR constant evaluation of enum discriminant resulted in non-integer
+    //~^ ERROR could not evaluate enum discriminant
 }
 
 fn main() {
diff --git a/src/test/compile-fail/feature-gate-tool_attributes.rs b/src/test/compile-fail/feature-gate-tool_attributes.rs
deleted file mode 100644 (file)
index 5a7536c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
-    let x =
-        3;
-}
diff --git a/src/test/compile-fail/issue-52489.rs b/src/test/compile-fail/issue-52489.rs
new file mode 100644 (file)
index 0000000..c43cc12
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// edition:2018
+// aux-build:issue-52489.rs
+
+use issue_52489;
+//~^ ERROR use of unstable library feature 'issue_52489_unstable'
+
+fn main() {}
diff --git a/src/test/compile-fail/lto-duplicate-symbols.rs b/src/test/compile-fail/lto-duplicate-symbols.rs
new file mode 100644 (file)
index 0000000..9c1dbfc
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:lto-duplicate-symbols1.rs
+// aux-build:lto-duplicate-symbols2.rs
+// error-pattern:Linking globals named 'foo': symbol multiply defined!
+// compile-flags: -C lto
+// no-prefer-dynamic
+
+extern crate lto_duplicate_symbols1;
+extern crate lto_duplicate_symbols2;
+
+fn main() {}
index c2192a21d90501026685cdeadd82c30dff2e3086..c4d22e6d392102ab9489797e4e844d04ecc31663 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_attributes)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
-#![foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
-
-#[foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
+#[foo::bar] //~ ERROR failed to resolve. Use of undeclared type or module `foo`
 fn main() {}
diff --git a/src/test/compile-fail/unknown_tool_attributes-1.rs b/src/test/compile-fail/unknown_tool_attributes-1.rs
deleted file mode 100644 (file)
index ba38c29..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Make sure that 'custom_attributes' feature does not allow scoped attributes.
-
-#![feature(custom_attributes)]
-
-#[foo::bar]
-//~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658]
-//~^^ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
-fn main() {}
index 3bf40b753c1feb5cbdb86350fcf33452ea09df16..910abfd5d7ee52aaf72296d33a20bf80d49d0ae8 100644 (file)
@@ -11,6 +11,6 @@
 #![deny(intra_doc_link_resolution_failure)]
 
 /// [intradoc::failure]
-fn main() {
+pub fn main() {
     println!("Hello, world!");
 }
index a3cd033f86382ed00a78ddcffa21806e6e716c19..87d2026fe2dc86c670c47c3a25df150aefe19468 100644 (file)
@@ -63,7 +63,7 @@ fn join_codegen_and_link(
         let crate_name = ongoing_codegen.downcast::<Symbol>()
             .expect("in join_codegen_and_link: ongoing_codegen is not a Symbol");
         for &crate_type in sess.opts.crate_types.iter() {
-            if crate_type != CrateType::CrateTypeRlib {
+            if crate_type != CrateType::Rlib {
                 sess.fatal(&format!("Crate type is {:?}", crate_type));
             }
             let output_name =
index 6f5e2affdbd3c3d33726a441350d7223ce98090e..d83b21e64415d1ddc21c9a30b8c717ad3e115a53 100644 (file)
@@ -19,7 +19,7 @@
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
-use rustc::session::config::{basic_options, Input, Options,
+use rustc::session::config::{Input, Options,
                              OutputType, OutputTypes};
 use rustc_driver::driver::{self, compile_input, CompileController};
 use rustc_metadata::cstore::CStore;
@@ -63,7 +63,7 @@ fn basic_sess(opts: Options) -> (Session, Rc<CStore>, Box<CodegenBackend>) {
 
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
     syntax::with_globals(|| {
-        let mut opts = basic_options();
+        let mut opts = Options::default();
         opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
         opts.maybe_sysroot = Some(sysroot);
         if let Ok(linker) = std::env::var("RUSTC_LINKER") {
index b3a6fb4d590ae279925001b94b39f85eaacdc8bd..cc2b6c641e90cd70d0bc08a841f43a1261b93205 100644 (file)
 extern crate rustc_codegen_utils;
 extern crate syntax;
 extern crate rustc_errors as errors;
+extern crate rustc_metadata;
 
-use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::session::config::{self, Input};
 use rustc_driver::{driver, CompilerCalls, Compilation};
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_metadata::cstore::CStore;
 use syntax::ast;
 
 use std::path::PathBuf;
@@ -51,7 +52,7 @@ fn late_callback(&mut self,
                      _: &CodegenBackend,
                      _: &getopts::Matches,
                      _: &Session,
-                     _: &CrateStore,
+                     _: &CStore,
                      _: &Input,
                      _: &Option<PathBuf>,
                      _: &Option<PathBuf>)
index df4a1d8994b5481b7c219f726026d71b12992345..d4af99f97c5c82001c5394169a6530cbce193145 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-42708.rs
 // ignore-stage1
 
-#![feature(decl_macro, use_extern_macros, proc_macro_path_invoc)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 extern crate issue_42708;
index 15dff94c88c180b1e11e468ec3dada2c9c9aefff..53783e7fedb2929ed865eed6dd49ae66a22e1fc7 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-50061.rs
 // ignore-stage1
 
-#![feature(use_extern_macros, proc_macro_path_invoc, decl_macro)]
+#![feature(proc_macro_path_invoc, decl_macro)]
 
 extern crate issue_50061;
 
diff --git a/src/test/run-pass/auxiliary/issue_38715-modern.rs b/src/test/run-pass/auxiliary/issue_38715-modern.rs
new file mode 100644 (file)
index 0000000..68aced7
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros)]
+#![allow(duplicate_macro_exports)]
+
+#[macro_export]
+macro_rules! foo_modern { ($i:ident) => {} }
+
+#[macro_export]
+macro_rules! foo_modern { () => {} }
index fa34b49210a6a5b90341da4a932df66a92341bea..95c738d3ec49a7301b510af618234e6dd57a5bdf 100644 (file)
@@ -25,7 +25,7 @@ fn main() {
     #[cfg(not(target_arch = "asmjs"))]
     {
         const BE_U128: u128 = 999999u128.to_be();
-        const LE_I128: i128 = -999999i128.to_le();
+        const LE_I128: i128 = (-999999i128).to_le();
         assert_eq!(BE_U128, b(999999u128).to_be());
         assert_eq!(LE_I128, b(-999999i128).to_le());
     }
diff --git a/src/test/run-pass/generator/yield-in-initializer.rs b/src/test/run-pass/generator/yield-in-initializer.rs
new file mode 100644 (file)
index 0000000..3042061
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators)]
+
+fn main() {
+    static || {
+        loop {
+            // Test that `opt` is not live across the yield, even when borrowed in a loop
+            // See https://github.com/rust-lang/rust/issues/52792
+            let opt = {
+                yield;
+                true
+            };
+            &opt;
+        }
+    };
+}
index 054785e62b8ea1c74d67de99aba10701e8c2c47b..b158234eb1154d98d0b872eefaa0fb5f97f1da10 100644 (file)
@@ -9,12 +9,16 @@
 // except according to those terms.
 
 // aux-build:issue_38715.rs
+// aux-build:issue_38715-modern.rs
 
 // Test that `#[macro_export] macro_rules!` shadow earlier `#[macro_export] macro_rules!`
 
 #[macro_use]
 extern crate issue_38715;
+#[macro_use]
+extern crate issue_38715_modern;
 
 fn main() {
     foo!();
+    foo_modern!();
 }
diff --git a/src/test/run-pass/issue-52557.rs b/src/test/run-pass/issue-52557.rs
new file mode 100644 (file)
index 0000000..2b8dfe1
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test checks for namespace pollution by private tests.
+// Tests used to marked as public causing name conflicts with normal
+// functions only in test builds.
+
+// compile-flags: --test
+
+mod a {
+    pub fn foo() -> bool {
+        true
+    }
+}
+
+mod b {
+    #[test]
+    fn foo() {
+        local_name(); // ensure the local name still works
+    }
+
+    #[test]
+    fn local_name() {}
+}
+
+use a::*;
+use b::*;
+
+pub fn conflict() {
+    let _: bool = foo();
+}
index cf417f8d412eeb93232039968efe2b9a74ef3c44..dbc65569afa876bab3c59bd270d7073c4ccd9483 100644 (file)
@@ -12,7 +12,7 @@ error[E0425]: cannot find value `no` in this scope
 3 | no
   | ^^ not found in this scope
 
-thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13
+thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:333:13
 note: Run with `RUST_BACKTRACE=1` for a backtrace.
 
 ---- $DIR/failed-doctest-output.rs - SomeStruct (line 20) stdout ----
@@ -21,7 +21,7 @@ thread '$DIR/failed-doctest-output.rs - SomeStruct (line 20)' panicked at 'test
 thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
 note: Run with `RUST_BACKTRACE=1` for a backtrace.
 
-', librustdoc/test.rs:367:17
+', librustdoc/test.rs:368:17
 
 
 failures:
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.rs b/src/test/rustdoc-ui/intra-doc-alias-ice.rs
new file mode 100644 (file)
index 0000000..a459ab5
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(intra_doc_link_resolution_failure)]
+
+pub type TypeAlias = usize;
+
+/// [broken cross-reference](TypeAlias::hoge) //~ ERROR
+pub fn some_public_item() {}
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr
new file mode 100644 (file)
index 0000000..2319639
--- /dev/null
@@ -0,0 +1,13 @@
+error: `[TypeAlias::hoge]` cannot be resolved, ignoring it...
+  --> $DIR/intra-doc-alias-ice.rs:15:30
+   |
+15 | /// [broken cross-reference](TypeAlias::hoge) //~ ERROR
+   |                              ^^^^^^^^^^^^^^^ cannot be resolved, ignoring
+   |
+note: lint level defined here
+  --> $DIR/intra-doc-alias-ice.rs:11:9
+   |
+11 | #![deny(intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
diff --git a/src/test/rustdoc/auxiliary/intra-link-extern-crate.rs b/src/test/rustdoc/auxiliary/intra-link-extern-crate.rs
new file mode 100644 (file)
index 0000000..e4a1944
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name="inner"]
+
+//! ooh, i'm a rebel just for [kicks]
index e2665fd8f375b5bc136c3142a3927b209946d16d..46e02ed08e00a72e0ab2f26e8b2d1c2d9a576d04 100644 (file)
@@ -17,6 +17,7 @@
 
 // @has foo/struct.Foo.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T'
 pub struct Foo;
+// @has foo/struct.Foo.html '//div[@class="sidebar-links"]/a[@href="#impl-ToString"]' 'ToString'
 
 impl fmt::Display for Foo {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/src/test/rustdoc/intra-link-extern-crate.rs b/src/test/rustdoc/intra-link-extern-crate.rs
new file mode 100644 (file)
index 0000000..5666f3b
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:intra-link-extern-crate.rs
+
+// When loading `extern crate` statements, we would pull in their docs at the same time, even
+// though they would never actually get displayed. This tripped intra-doc-link resolution failures,
+// for items that aren't under our control, and not actually getting documented!
+
+#![deny(intra_doc_link_resolution_failure)]
+
+extern crate inner;
diff --git a/src/test/rustdoc/intra-link-private.rs b/src/test/rustdoc/intra-link-private.rs
new file mode 100644 (file)
index 0000000..dbdfbc4
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Rustdoc would previously report resolution failures on items that weren't in the public docs.
+// These failures were legitimate, but not truly relevant - the docs in question couldn't be
+// checked for accuracy anyway.
+
+#![deny(intra_doc_link_resolution_failure)]
+
+/// ooh, i'm a [rebel] just for kicks
+struct SomeStruct;
diff --git a/src/test/rustdoc/primitive-generic-impl.rs b/src/test/rustdoc/primitive-generic-impl.rs
new file mode 100644 (file)
index 0000000..b4351b8
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// we need to reexport something from libstd so that `all_trait_implementations` is called.
+pub use std::string::String;
+
+include!("primitive/primitive-generic-impl.rs");
+
+// @has foo/primitive.i32.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T'
diff --git a/src/test/rustdoc/primitive/primitive-generic-impl.rs b/src/test/rustdoc/primitive/primitive-generic-impl.rs
new file mode 100644 (file)
index 0000000..1ac1fc9
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-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(primitive = "i32")]
+/// Some useless docs, wouhou!
+mod i32 {}
diff --git a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
new file mode 100644 (file)
index 0000000..01fa2f3
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(plugin_registrar)]
+#![feature(box_syntax, rustc_private)]
+#![feature(macro_vis_matcher)]
+#![feature(macro_at_most_once_rep)]
+
+extern crate syntax;
+
+// Load rustc as a plugin to get macros
+#[macro_use]
+extern crate rustc;
+extern crate rustc_plugin;
+
+use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
+                  LintArray};
+use rustc_plugin::Registry;
+use syntax::ast;
+declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
+
+struct Pass;
+
+impl LintPass for Pass {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(TEST_LINT)
+    }
+}
+
+impl EarlyLintPass for Pass {
+    fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
+        if it.ident.name == "lintme" {
+            cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
+        }
+    }
+}
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_early_lint_pass(box Pass);
+}
diff --git a/src/test/ui-fulldeps/lint_tool_test.rs b/src/test/ui-fulldeps/lint_tool_test.rs
new file mode 100644 (file)
index 0000000..ccdcd2d
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// aux-build:lint_tool_test.rs
+// ignore-stage1
+#![feature(plugin)]
+#![feature(tool_lints)]
+#![plugin(lint_tool_test)]
+#![allow(dead_code)]
+
+fn lintme() { } //~ WARNING item is named 'lintme'
+
+#[allow(clippy::test_lint)]
+pub fn main() {
+    fn lintme() { }
+}
diff --git a/src/test/ui-fulldeps/lint_tool_test.stderr b/src/test/ui-fulldeps/lint_tool_test.stderr
new file mode 100644 (file)
index 0000000..22d0f45
--- /dev/null
@@ -0,0 +1,8 @@
+warning: item is named 'lintme'
+  --> $DIR/lint_tool_test.rs:19:1
+   |
+LL | fn lintme() { } //~ WARNING item is named 'lintme'
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(clippy::test_lint)] on by default
+
index a60841d848c16363ac56f08e03cd04abf7d2e858..18f5b0f506cc2f7b9e78aa49ec730ff4b6fcac4c 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:parent-source-spans.rs
 // ignore-stage1
 
-#![feature(use_extern_macros, decl_macro, proc_macro_non_items)]
+#![feature(decl_macro, proc_macro_non_items)]
 
 extern crate parent_source_spans;
 
diff --git a/src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs b/src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs
new file mode 100644 (file)
index 0000000..7ae4731
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn foo(_attr: TokenStream, _f: TokenStream) -> TokenStream {
+    "pub fn foo() -> ::Foo { ::Foo }".parse().unwrap()
+}
diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed
new file mode 100644 (file)
index 0000000..e5b47c7
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:suggestions-not-always-applicable.rs
+// compile-flags: --edition 2015
+// run-rustfix
+// rustfix-only-machine-applicable
+// compile-pass
+
+#![feature(rust_2018_preview)]
+#![warn(rust_2018_compatibility)]
+
+extern crate suggestions_not_always_applicable as foo;
+
+pub struct Foo;
+
+mod test {
+    use crate::foo::foo;
+
+    #[foo] //~ WARN: absolute paths must start with
+    //~| WARN: previously accepted
+    //~| WARN: absolute paths
+    //~| WARN: previously accepted
+    fn main() {
+    }
+}
+
+fn main() {
+    test::foo();
+}
diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs
new file mode 100644 (file)
index 0000000..e5b47c7
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:suggestions-not-always-applicable.rs
+// compile-flags: --edition 2015
+// run-rustfix
+// rustfix-only-machine-applicable
+// compile-pass
+
+#![feature(rust_2018_preview)]
+#![warn(rust_2018_compatibility)]
+
+extern crate suggestions_not_always_applicable as foo;
+
+pub struct Foo;
+
+mod test {
+    use crate::foo::foo;
+
+    #[foo] //~ WARN: absolute paths must start with
+    //~| WARN: previously accepted
+    //~| WARN: absolute paths
+    //~| WARN: previously accepted
+    fn main() {
+    }
+}
+
+fn main() {
+    test::foo();
+}
diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr
new file mode 100644 (file)
index 0000000..76dc139
--- /dev/null
@@ -0,0 +1,24 @@
+warning: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/suggestions-not-always-applicable.rs:27:5
+   |
+LL |     #[foo] //~ WARN: absolute paths must start with
+   |     ^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/suggestions-not-always-applicable.rs:18:9
+   |
+LL | #![warn(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[warn(absolute_paths_not_starting_with_crate)] implied by #[warn(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+warning: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/suggestions-not-always-applicable.rs:27:5
+   |
+LL |     #[foo] //~ WARN: absolute paths must start with
+   |     ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
index fbd58cd4c2260adc3212068169d9ba3ee27672a7..45b0c84275be46ef203595a015511bd35870a775 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `x`
-  --> $DIR/asm-out-assign-imm.rs:33:9
+  --> $DIR/asm-out-assign-imm.rs:34:9
    |
 LL |     let x: isize;
    |         - consider changing this to `mut x`
index f5bb07a9b35aacb265ef2655c43fc9fffd15b2e7..73143f1154631be50106dbf82ee28d79e985a0f7 100644 (file)
@@ -16,6 +16,7 @@
 // ignore-sparc
 // ignore-sparc64
 // ignore-mips
+// ignore-mips64
 
 #![feature(asm)]
 
index 7075914fa04bd35cfdff6e5278841bc941fcfb25..83cb8092e16a29e7174f5e24a616e8bbfa610ba6 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `x`
-  --> $DIR/asm-out-assign-imm.rs:33:9
+  --> $DIR/asm-out-assign-imm.rs:34:9
    |
 LL |     x = 1;
    |     ----- first assignment to `x`
diff --git a/src/test/ui/async-matches-expr.rs b/src/test/ui/async-matches-expr.rs
new file mode 100644 (file)
index 0000000..d6959f9
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro)]
+
+macro_rules! match_expr {
+    ($x:expr) => {}
+}
+
+fn main() {
+    match_expr!(async {});
+    match_expr!(async || {});
+}
index 01282f2ad24b2daf57af8ae346e724947a3e9a4b..c787cedc2d0ea10b5880ac5a76139858fb377427 100644 (file)
@@ -12,3 +12,8 @@
 macro_rules! mac {
     ($ident:ident) => { let $ident = 42; }
 }
+
+#[macro_export]
+macro_rules! inline {
+    () => ()
+}
index a4f8e8b408ba501b15e6783764e00a01b8e309f0..6186c3839193d0dd3aa23c038fd71befd8371997 100644 (file)
@@ -77,11 +77,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:24:24
    |
 LL |     let c1 = to_fn_mut(|| x = 4);
-   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        -- - first borrow occurs due to use of `x` in closure
    |                        |
    |                        first mutable borrow occurs here
 LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
-   |                        ^^ - borrow occurs due to use of `x` in closure
+   |                        ^^ - second borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
@@ -92,11 +92,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:36:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut x));
-   |                        --          - previous borrow occurs due to use of `x` in closure
+   |                        --          - first borrow occurs due to use of `x` in closure
    |                        |
    |                        first mutable borrow occurs here
 LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
-   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        ^^          - second borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
@@ -107,11 +107,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:44:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
-   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        -- - first borrow occurs due to use of `x` in closure
    |                        |
    |                        first mutable borrow occurs here
 LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
-   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        ^^          - second borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
@@ -122,11 +122,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:52:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
-   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        -- - first borrow occurs due to use of `x` in closure
    |                        |
    |                        first mutable borrow occurs here
 LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
-   |                        ^^                                  - borrow occurs due to use of `x` in closure
+   |                        ^^                                  - second borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
 ...
@@ -137,11 +137,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:65:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
-   |                        --           - previous borrow occurs due to use of `x` in closure
+   |                        --           - first borrow occurs due to use of `x` in closure
    |                        |
    |                        first mutable borrow occurs here
 LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
-   |                        ^^           - borrow occurs due to use of `x` in closure
+   |                        ^^           - second borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
 ...
index b15f156b7c2013510162f1d3a1a1ed7281a14c99..426419a7b3b7f830a10d2aeb87a2a388846010d1 100644 (file)
@@ -1,8 +1,10 @@
 error[E0597]: `books` does not live long enough
-  --> $DIR/borrowck-escaping-closure-error-1.rs:23:11
+  --> $DIR/borrowck-escaping-closure-error-1.rs:23:14
    |
 LL |     spawn(|| books.push(4));
-   |           ^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |           -- ^^^^^ borrowed value does not live long enough
+   |           |
+   |           value captured here
 LL |     //~^ ERROR E0373
 LL | }
    | - `books` dropped here while still borrowed
index 8c643973af67b85f8b850a69bf3817a4a4c6e0b9..d5f3a0ed6d82eb082c216adb23b729492dc288fe 100644 (file)
@@ -1,8 +1,10 @@
 error[E0597]: `books` does not live long enough
-  --> $DIR/borrowck-escaping-closure-error-2.rs:21:14
+  --> $DIR/borrowck-escaping-closure-error-2.rs:21:17
    |
 LL |     Box::new(|| books.push(4))
-   |              ^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |              -- ^^^^^ borrowed value does not live long enough
+   |              |
+   |              value captured here
 LL |     //~^ ERROR E0373
 LL | }
    | - `books` dropped here while still borrowed
index a34c97974da110360c9a96b768bb5258e36b46d6..1b913471924b799a19fbcefa11978ce2bef67d0a 100644 (file)
@@ -19,14 +19,16 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
    |
 LL |     match (S {f: "foo".to_string(), g: "bar".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
+...
+LL |             f: _s,
+   |                -- data moved here
+LL |             g: _t
+   |                -- ... and here
 help: to prevent move, use ref or ref mut
    |
 LL |             f: ref _s,
-   |                ^^^^^^
-help: to prevent move, use ref or ref mut
-   |
 LL |             g: ref _t
-   |                ^^^^^^
+   |
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-error-with-note.rs:57:11
index d01b24507d9fe390ba6d72d208d07ef4144da6a6..95a7894d532546e1f8dd942b7c11e536c906eb22 100644 (file)
@@ -3,14 +3,19 @@ error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
    |
 LL |             match tail {
    |                   ^^^^ cannot move out of here
+LL |                 &[Foo { string: a },
+   |                                 - data moved here
+...
+LL |                   Foo { string: b }] => {
+   |                                 - ... and here
 help: to prevent move, use ref or ref mut
    |
 LL |                 &[Foo { string: ref a },
-   |                                 ^^^^^
-help: to prevent move, use ref or ref mut
-   |
+LL |                 //~^ ERROR cannot move out of type `[Foo]`
+LL |                 //~| cannot move out
+LL |                 //~| to prevent move
 LL |                   Foo { string: ref b }] => {
-   |                                 ^^^^^
+   |
 
 error: aborting due to previous error
 
index 50ef3ba40e7b23afc6a5ad665c1f3f6d91d4000d..2779132590e2c00b57e1b06f1a9d372b2af166fd 100644 (file)
@@ -28,7 +28,10 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
 LL |     match vec {
    |           ^^^ cannot move out of here
 LL |         &mut [_a, //~ ERROR cannot move out
-   |               -- help: to prevent move, use ref or ref mut: `ref _a`
+   |               --
+   |               |
+   |               data moved here
+   |               help: to prevent move, use ref or ref mut: `ref _a`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:57:13
@@ -46,7 +49,10 @@ LL |     match vec {
    |           ^^^ cannot move out of here
 ...
 LL |          _b] => {}
-   |          -- help: to prevent move, use ref or ref mut: `ref _b`
+   |          --
+   |          |
+   |          data moved here
+   |          help: to prevent move, use ref or ref mut: `ref _b`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:70:13
@@ -62,18 +68,15 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
+LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
+   |               --  --  -- ... and here
+   |               |   |
+   |               |   ... and here
+   |               data moved here
 help: to prevent move, use ref or ref mut
    |
-LL |         &mut [ref _a, _b, _c] => {}  //~ ERROR cannot move out
-   |               ^^^^^^
-help: to prevent move, use ref or ref mut
-   |
-LL |         &mut [_a, ref _b, _c] => {}  //~ ERROR cannot move out
-   |                   ^^^^^^
-help: to prevent move, use ref or ref mut
-   |
-LL |         &mut [_a, _b, ref _c] => {}  //~ ERROR cannot move out
-   |                       ^^^^^^
+LL |         &mut [ref _a, ref _b, ref _c] => {}  //~ ERROR cannot move out
+   |               ^^^^^^  ^^^^^^  ^^^^^^
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:82:13
index 4048243acfa2b12aa20b5757c75f411370c0b861..b6e005a6673ebc53a74a9e3c0cdb1dbd33daf99f 100644 (file)
@@ -17,41 +17,41 @@ LL |         if let Some(thing) = maybe {
    = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:30
+  --> $DIR/issue-41962.rs:17:16
    |
 LL |         if let Some(thing) = maybe {
-   |                     -----    ^^^^^ value used here after move
-   |                     |
-   |                     value moved here
+   |                ^^^^^-----^
+   |                |    |
+   |                |    value moved here
+   |                value used here after move
    |
    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:30
+error[E0382]: use of moved value (Mir)
+  --> $DIR/issue-41962.rs:17:21
    |
 LL |         if let Some(thing) = maybe {
-   |                     -----    ^^^^^ value borrowed here after move
-   |                     |
-   |                     value moved here
+   |                     ^^^^^ value moved here in previous iteration of loop
    |
    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:16
+  --> $DIR/issue-41962.rs:17:30
    |
 LL |         if let Some(thing) = maybe {
-   |                ^^^^^-----^
-   |                |    |
-   |                |    value moved here
-   |                value used here after move
+   |                     -----    ^^^^^ value used here after move
+   |                     |
+   |                     value moved here
    |
    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value (Mir)
-  --> $DIR/issue-41962.rs:17:21
+error[E0382]: borrow of moved value: `maybe` (Mir)
+  --> $DIR/issue-41962.rs:17:30
    |
 LL |         if let Some(thing) = maybe {
-   |                     ^^^^^ value moved here in previous iteration of loop
+   |                     -----    ^^^^^ value borrowed here after move
+   |                     |
+   |                     value moved here
    |
    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
index d872c7efe2bc116dca0abdd552dcf4aec7b3888c..20713c3392e8e9c23e0f2cfe66337beee321ede3 100644 (file)
@@ -4,6 +4,7 @@ error[E0507]: cannot move out of borrowed content
 LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
    |                                          ^^^^^-^
    |                                          |    |
+   |                                          |    data moved here
    |                                          |    help: to prevent move, use ref or ref mut: `ref s`
    |                                          cannot move out of borrowed content
 
diff --git a/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs b/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs
new file mode 100644 (file)
index 0000000..c39fff2
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This is a regression test for #52967, where we discovered that in
+// the initial deployment of NLL for the 2018 edition, I forgot to
+// turn on two-phase-borrows in addition to `-Z borrowck=migrate`.
+
+// revisions: ast zflags edition
+//[zflags]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[edition]compile-flags: --edition 2018
+
+// run-pass
+
+fn the_bug() {
+    let mut stuff = ("left", "right");
+    match stuff {
+        (ref mut left, _) if *left == "left" => { *left = "new left"; }
+        _ => {}
+    }
+    assert_eq!(stuff, ("new left", "right"));
+}
+
+fn main() {
+    the_bug();
+}
index 55f57e97ba4fa3c968a2e634009437cdba15b206..02e5b44c17c4acc0baf53689129655a108654e41 100644 (file)
@@ -17,7 +17,7 @@ LL |         let inner_second = &mut inner_void; //~ ERROR cannot borrow
    |                            ^^^^^^^^^^^^^^^ second mutable borrow occurs here
 LL |         inner_second.use_mut();
 LL |         inner_first.use_mut();
-   |         ----------- borrow later used here
+   |         ----------- borrow used here in later iteration of loop
 
 error: aborting due to 2 previous errors
 
index 95acdab3e80012e3c7c94d179e2667901c7fc3b2..52f1547bce6f86f33b7bcd359e41186aef326d06 100644 (file)
@@ -1,30 +1,24 @@
 error[E0597]: borrowed value does not live long enough
   --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:21
    |
-LL |   fn gimme_static_mut_let() -> &'static mut u32 {
-   |  _______________________________________________-
-LL | |     let ref mut x = 1234543; //~ ERROR
-   | |                     ^^^^^^^ temporary value does not live long enough
-LL | |     x
-LL | | }
-   | | -
-   | | |
-   | |_temporary value only lives until here
-   |   borrow later used here
+LL |     let ref mut x = 1234543; //~ ERROR
+   |                     ^^^^^^^ temporary value does not live long enough
+LL |     x
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
   --> $DIR/promote-ref-mut-in-let-issue-46557.rs:20:25
    |
-LL |   fn gimme_static_mut_let_nested() -> &'static mut u32 {
-   |  ______________________________________________________-
-LL | |     let (ref mut x, ) = (1234543, ); //~ ERROR
-   | |                         ^^^^^^^^^^^ temporary value does not live long enough
-LL | |     x
-LL | | }
-   | | -
-   | | |
-   | |_temporary value only lives until here
-   |   borrow later used here
+LL |     let (ref mut x, ) = (1234543, ); //~ ERROR
+   |                         ^^^^^^^^^^^ temporary value does not live long enough
+LL |     x
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
   --> $DIR/promote-ref-mut-in-let-issue-46557.rs:25:11
index 0c02acf6548557eac0d3106a4387ad77adf67921..a7e1dd95364533bb206d2b95b9b039c272c99f7d 100644 (file)
@@ -1,21 +1,21 @@
 error[E0499]: cannot borrow `foo` as mutable more than once at a time
-  --> $DIR/two-phase-multi-mut.rs:23:16
+  --> $DIR/two-phase-multi-mut.rs:23:5
    |
 LL |     foo.method(&mut foo);
-   |     -----------^^^^^^^^-
+   |     ^^^^^^^^^^^--------^
    |     |          |
-   |     |          second mutable borrow occurs here
-   |     first mutable borrow occurs here
+   |     |          first mutable borrow occurs here
+   |     second mutable borrow occurs here
    |     borrow later used here
 
 error[E0499]: cannot borrow `foo` as mutable more than once at a time
-  --> $DIR/two-phase-multi-mut.rs:23:5
+  --> $DIR/two-phase-multi-mut.rs:23:16
    |
 LL |     foo.method(&mut foo);
-   |     ^^^^^^^^^^^--------^
+   |     -----------^^^^^^^^-
    |     |          |
-   |     |          first mutable borrow occurs here
-   |     second mutable borrow occurs here
+   |     |          second mutable borrow occurs here
+   |     first mutable borrow occurs here
    |     borrow later used here
 
 error: aborting due to 2 previous errors
index 34616a8de45ed9882743c67058448700e39b5133..a1fbcf1430db93b2b4a40c3077ee87db39a4cce9 100644 (file)
@@ -4,7 +4,10 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         S {f:_s} => {} //~ ERROR cannot move out
-   |              -- help: to prevent move, use ref or ref mut: `ref _s`
+   |              --
+   |              |
+   |              data moved here
+   |              help: to prevent move, use ref or ref mut: `ref _s`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-eval/simple_with_undef.rs b/src/test/ui/const-eval/simple_with_undef.rs
new file mode 100644 (file)
index 0000000..d18059f
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+const PARSE_BOOL: Option<&'static str> = None;
+static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42);
+
+fn main() {}
index 41981e1256791551bba81f345f8e89ba7e48c285..5723f4a4159aa5170a8020efe2404afd09398fd8 100644 (file)
@@ -34,7 +34,7 @@ const fn read_field2() -> Field2 {
 }
 
 const fn read_field3() -> Field3 {
-    const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR exhibits undefined behavior
+    const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR cannot be used
     FIELD3
 }
 
index 94896d6c22577b4b7109f997caf440414926c8e5..811450c8cba4757afc3b52765633e357a00aec7c 100644 (file)
@@ -1,11 +1,10 @@
-error[E0080]: this constant likely exhibits undefined behavior
+error: this constant cannot be used
   --> $DIR/union-const-eval-field.rs:37:5
    |
-LL |     const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR exhibits undefined behavior
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined bytes
+LL |     const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR cannot be used
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: #[deny(const_err)] on by default
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
index 426710389eb2951e386426857e1eca1000bbca89..0cdb78c97803c7f80cf3ef89614173154971812f 100644 (file)
@@ -20,9 +20,9 @@ union DummyUnion {
 
 const UNION: DummyUnion = DummyUnion { field1: 1065353216 };
 
-const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant likely exhibits undefined
+const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant cannot be used
 
-const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibits undefined behavior
+const FIELD_PATH: Struct = Struct { //~ ERROR this constant cannot be used
     a: 42,
     b: unsafe { UNION.field3 },
 };
index 58e9033a071a1209a01b1caf041e14697cd55ab3..e8a7b2f500561e31cbee5926bd8b7d8893e1d003 100644 (file)
@@ -1,21 +1,19 @@
-error[E0080]: this constant likely exhibits undefined behavior
+error: this constant cannot be used
   --> $DIR/union-ice.rs:23:1
    |
-LL | const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant likely exhibits undefined
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined bytes
+LL | const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant cannot be used
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: #[deny(const_err)] on by default
 
-error[E0080]: this constant likely exhibits undefined behavior
+error: this constant cannot be used
   --> $DIR/union-ice.rs:25:1
    |
-LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibits undefined behavior
+LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant cannot be used
 LL | |     a: 42,
 LL | |     b: unsafe { UNION.field3 },
 LL | | };
-   | |__^ type validation failed: encountered undefined bytes at .b
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   | |__^ attempted to read undefined bytes
 
 error[E0080]: this constant likely exhibits undefined behavior
   --> $DIR/union-ice.rs:35:1
index 00e4cc6b0c35d459ebb2f4910e85c47545c3ba95..8c848b33241ca44ea8e19912e0e91ec53f6f6955 100644 (file)
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:26:17
    |
 LL |     fn foo<'z>(&'z self) {
-   |                -------- help: consider changing this to be a mutable reference: `&mut self`
+   |                -------- help: consider changing this to be a mutable reference: `&'z mut self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -35,7 +35,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:35:17
    |
 LL |     fn foo2<'a>(&'a self, other: &Z) {
-   |                 -------- help: consider changing this to be a mutable reference: `&mut self`
+   |                 -------- help: consider changing this to be a mutable reference: `&'a mut self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -52,7 +52,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:40:17
    |
 LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
-   |                       -------- help: consider changing this to be a mutable reference: `&mut Z`
+   |                       -------- help: consider changing this to be a mutable reference: `&'a mut Self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
index d874a43d53d793ab11a94b947745d1c8bf915457..d8159bff567ad18cf7bb6178ce9602e8188cd255 100644 (file)
@@ -13,6 +13,6 @@
 pub use std::panic;
 
 #[macro_export]
-macro_rules! panic { () => {} } //~ ERROR a macro named `panic` has already been exported
+macro_rules! panic { () => {} } //~ ERROR the name `panic` is defined multiple times
 
 fn main() {}
index 6d3bb669df975bb84292f1953118bcaa4e1c019c..651e984b274528f4ff5a4aff47b032db88c30789 100644 (file)
@@ -1,14 +1,18 @@
-error: a macro named `panic` has already been exported
+error[E0255]: the name `panic` is defined multiple times
   --> $DIR/duplicate-check-macro-exports.rs:16:1
    |
-LL | macro_rules! panic { () => {} } //~ ERROR a macro named `panic` has already been exported
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `panic` already exported
+LL | pub use std::panic;
+   |         ---------- previous import of the macro `panic` here
+...
+LL | macro_rules! panic { () => {} } //~ ERROR the name `panic` is defined multiple times
+   | ^^^^^^^^^^^^^^^^^^ `panic` redefined here
    |
-note: previous macro export here
-  --> $DIR/duplicate-check-macro-exports.rs:13:9
+   = note: `panic` must be defined only once in the macro namespace of this module
+help: You can use `as` to change the binding name of the import
    |
-LL | pub use std::panic;
-   |         ^^^^^^^^^^
+LL | pub use std::panic as other_panic;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0255`.
index ec30bb306fc3fd3d2e539ce69cd1edddfa5b8743..6f4823326ffa6a0abf9d2db4c240d96bdb00eb5a 100644 (file)
@@ -1,17 +1,16 @@
 error[E0505]: cannot move out of `fancy_num` because it is borrowed
   --> $DIR/E0504.rs:19:13
    |
-LL |       let fancy_ref = &fancy_num;
-   |                       ---------- borrow of `fancy_num` occurs here
+LL |     let fancy_ref = &fancy_num;
+   |                     ---------- borrow of `fancy_num` occurs here
 LL | 
-LL |       let x = move || {
-   |  _____________^
-LL | |         println!("child function: {}", fancy_num.num); //~ ERROR E0504
-LL | |     };
-   | |_____^ move out of `fancy_num` occurs here
+LL |     let x = move || {
+   |             ^^^^^^^ move out of `fancy_num` occurs here
+LL |         println!("child function: {}", fancy_num.num); //~ ERROR E0504
+   |                                        --------- move occurs due to use in closure
 ...
-LL |       println!("main function: {}", fancy_ref.num);
-   |                                     ------------- borrow later used here
+LL |     println!("main function: {}", fancy_ref.num);
+   |                                   ------------- borrow later used here
 
 error: aborting due to previous error
 
index 748adc390d8bbf3025e911461c388a5ffe7db99c..5d7e01fbbb752d895d42b4468c9abfffaa5cefb5 100644 (file)
@@ -1,4 +1,4 @@
-error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
   --> $DIR/feature-gate-macros_in_extern.rs:29:5
    |
 LL |     returns_isize!(rust_get_test_int);
@@ -6,7 +6,7 @@ LL |     returns_isize!(rust_get_test_int);
    |
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
   --> $DIR/feature-gate-macros_in_extern.rs:31:5
    |
 LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
@@ -14,7 +14,7 @@ LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
    |
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
   --> $DIR/feature-gate-macros_in_extern.rs:33:5
    |
 LL |     emits_nothing!();
index 2b7cf56d9381291f1aed2a4fa13af3dc1a0677c4..47c623574ec90ef84e77f3357dbcb6ae588967d1 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(use_extern_macros)]
+
 fn main() {
-    #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
+    #[rustfmt::skip] //~ ERROR tool attributes are unstable
     let x = 3
         ;
 }
index da89c4a5ef692634badba632f031afb2c0009dcb..ebc266e004ecceaf293e746e76cadd471d4e4f79 100644 (file)
@@ -1,7 +1,7 @@
-error[E0658]: scoped attribute `rustfmt::skip` is experimental (see issue #44690)
-  --> $DIR/feature-gate-tool_attributes.rs:12:5
+error[E0658]: tool attributes are unstable (see issue #44690)
+  --> $DIR/feature-gate-tool_attributes.rs:14:5
    |
-LL |     #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
+LL |     #[rustfmt::skip] //~ ERROR tool attributes are unstable
    |     ^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(tool_attributes)] to the crate attributes to enable
index ef7e64ffd97ae251494a68b10e5b8548955c115b..b49bf81715079006535a47584eeeb1917b104e59 100644 (file)
@@ -9,8 +9,6 @@ LL | }
    | |
    | `*cell` dropped here while still borrowed
    | borrow later used here, when `gen` is dropped
-   |
-   = note: values in a scope are dropped in the opposite order they are defined
 
 error[E0597]: `ref_` does not live long enough
   --> $DIR/dropck.rs:22:11
index 51f8067b8ce5b8428fe7ce654113a275c24585c0..56b77714991ca61e7d5d5ca72684aad75686a1cb 100644 (file)
@@ -1,27 +1,27 @@
 error[E0382]: use of moved value: `foo.x`
-  --> $DIR/fields-move.rs:38:42
+  --> $DIR/fields-move.rs:28:9
    |
 LL |    $foo.x
    |    ------ value moved here
 ...
+LL |         $foo.x //~ ERROR use of moved value: `foo.x`
+   |         ^^^^^^ value used here after move
+...
 LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
-   |                                          ^^^^^ value used here after move
+   |                                          ----- value moved here
+LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                       ----------------- in this macro invocation
    |
    = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `foo.x`
-  --> $DIR/fields-move.rs:28:9
+  --> $DIR/fields-move.rs:38:42
    |
 LL |    $foo.x
    |    ------ value moved here
 ...
-LL |         $foo.x //~ ERROR use of moved value: `foo.x`
-   |         ^^^^^^ value used here after move
-...
 LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
-   |                                          ----- value moved here
-LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
-   |                       ----------------- in this macro invocation
+   |                                          ^^^^^ value used here after move
    |
    = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
 
index bbc63e6fecaf5c7b790f1c9bf64e2a0720d98e61..c1e12978c5179c057186d2390b66e71cbafab4d3 100644 (file)
@@ -21,6 +21,8 @@ LL |         self.x.iter().map(|a| a.0)
 error: unsatisfied lifetime constraints
   --> $DIR/static-return-lifetime-infered.rs:21:9
    |
+LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+   |                    -- lifetime `'a` defined here
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
 
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
new file mode 100644 (file)
index 0000000..4453447
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+macro_rules! define_exported { () => {
+    #[macro_export]
+    macro_rules! exported {
+        () => ()
+    }
+}}
+macro_rules! define_panic { () => {
+    #[macro_export]
+    macro_rules! panic {
+        () => ()
+    }
+}}
+macro_rules! define_include { () => {
+    #[macro_export]
+    macro_rules! include {
+        () => ()
+    }
+}}
+
+use inner1::*;
+
+mod inner1 {
+    pub macro exported() {}
+}
+
+exported!(); //~ ERROR `exported` is ambiguous
+
+mod inner2 {
+    define_exported!();
+}
+
+fn main() {
+    panic!(); //~ ERROR `panic` is ambiguous
+              //~^ ERROR `panic` is ambiguous
+}
+
+mod inner3 {
+    define_panic!();
+}
+
+mod inner4 {
+    define_include!();
+}
+
+include!(); //~ ERROR `include` is ambiguous
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
new file mode 100644 (file)
index 0000000..e9a81e7
--- /dev/null
@@ -0,0 +1,84 @@
+error[E0659]: `exported` is ambiguous
+  --> $DIR/local-modularized-tricky-fail-1.rs:38:1
+   |
+LL | exported!(); //~ ERROR `exported` is ambiguous
+   | ^^^^^^^^
+   |
+note: `exported` could refer to the name defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:15:5
+   |
+LL | /     macro_rules! exported {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_exported!();
+   |       ------------------- in this macro invocation
+note: `exported` could also refer to the name imported here
+  --> $DIR/local-modularized-tricky-fail-1.rs:32:5
+   |
+LL | use inner1::*;
+   |     ^^^^^^^^^
+   = note: macro-expanded macros do not shadow
+
+error[E0659]: `include` is ambiguous
+  --> $DIR/local-modularized-tricky-fail-1.rs:57:1
+   |
+LL | include!(); //~ ERROR `include` is ambiguous
+   | ^^^^^^^
+   |
+note: `include` could refer to the name defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:27:5
+   |
+LL | /     macro_rules! include {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_include!();
+   |       ------------------ in this macro invocation
+   = note: `include` is also a builtin macro
+   = note: macro-expanded macros do not shadow
+
+error[E0659]: `panic` is ambiguous
+  --> $DIR/local-modularized-tricky-fail-1.rs:45:5
+   |
+LL |     panic!(); //~ ERROR `panic` is ambiguous
+   |     ^^^^^
+   |
+note: `panic` could refer to the name defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:21:5
+   |
+LL | /     macro_rules! panic {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_panic!();
+   |       ---------------- in this macro invocation
+   = note: `panic` is also a builtin macro
+   = note: macro-expanded macros do not shadow
+
+error[E0659]: `panic` is ambiguous
+  --> $DIR/local-modularized-tricky-fail-1.rs:45:5
+   |
+LL |     panic!(); //~ ERROR `panic` is ambiguous
+   |     ^^^^^^^^^
+   |
+note: `panic` could refer to the name defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:21:5
+   |
+LL | /     macro_rules! panic {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_panic!();
+   |       ---------------- in this macro invocation
+   = note: `panic` is also a builtin macro
+   = note: macro-expanded macros do not shadow
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.rs b/src/test/ui/imports/local-modularized-tricky-fail-2.rs
new file mode 100644 (file)
index 0000000..afdebc4
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// `#[macro_export] macro_rules` that doen't originate from macro expansions can be placed
+// into the root module soon enough to act as usual items and shadow globs and preludes.
+
+#![feature(decl_macro)]
+
+// `macro_export` shadows globs
+use inner1::*;
+
+mod inner1 {
+    pub macro exported() {}
+}
+
+exported!();
+
+mod deep {
+    fn deep() {
+        type Deeper = [u8; {
+            #[macro_export]
+            macro_rules! exported {
+                () => ( struct Б; ) //~ ERROR non-ascii idents are not fully supported
+            }
+
+            0
+        }];
+    }
+}
+
+// `macro_export` shadows std prelude
+fn main() {
+    panic!();
+}
+
+mod inner3 {
+    #[macro_export]
+    macro_rules! panic {
+        () => ( struct Г; ) //~ ERROR non-ascii idents are not fully supported
+    }
+}
+
+// `macro_export` shadows builtin macros
+include!();
+
+mod inner4 {
+    #[macro_export]
+    macro_rules! include {
+        () => ( struct Д; ) //~ ERROR non-ascii idents are not fully supported
+    }
+}
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
new file mode 100644 (file)
index 0000000..5681dd5
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/local-modularized-tricky-fail-2.rs:30:32
+   |
+LL | exported!();
+   | ------------ in this macro invocation
+...
+LL |                 () => ( struct Б; ) //~ ERROR non-ascii idents are not fully supported
+   |                                ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/local-modularized-tricky-fail-2.rs:46:24
+   |
+LL |     panic!();
+   |     --------- in this macro invocation
+...
+LL |         () => ( struct Г; ) //~ ERROR non-ascii idents are not fully supported
+   |                        ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/local-modularized-tricky-fail-2.rs:56:24
+   |
+LL | include!();
+   | ----------- in this macro invocation
+...
+LL |         () => ( struct Д; ) //~ ERROR non-ascii idents are not fully supported
+   |                        ^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/imports/local-modularized-tricky-pass.rs b/src/test/ui/imports/local-modularized-tricky-pass.rs
new file mode 100644 (file)
index 0000000..04df357
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(use_extern_macros)]
+
+macro_rules! define_exported { () => {
+    #[macro_export]
+    macro_rules! exported {
+        () => ()
+    }
+}}
+
+mod inner1 {
+    use super::*;
+    exported!();
+}
+
+mod inner2 {
+    define_exported!();
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/local-modularized.rs b/src/test/ui/imports/local-modularized.rs
new file mode 100644 (file)
index 0000000..a5297c5
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(use_extern_macros)]
+
+#[macro_export(local_inner_macros)]
+macro_rules! dollar_crate_exported {
+    (1) => { $crate::exported!(); };
+    (2) => { exported!(); };
+}
+
+// Before `exported` is defined
+exported!();
+
+mod inner {
+
+    ::exported!();
+    crate::exported!();
+    dollar_crate_exported!(1);
+    dollar_crate_exported!(2);
+
+    mod inner_inner {
+        #[macro_export]
+        macro_rules! exported {
+            () => ()
+        }
+    }
+
+    // After `exported` is defined
+    ::exported!();
+    crate::exported!();
+    dollar_crate_exported!(1);
+    dollar_crate_exported!(2);
+}
+
+exported!();
+
+fn main() {}
index 6de00ffd48cc1ddd230c715d4c922ed6cae74491..48dad040f9d0cd64c1ea84a737836d9789f4c3bd 100644 (file)
@@ -7,6 +7,8 @@ LL |         x //~ ERROR E0312
 error: unsatisfied lifetime constraints
   --> $DIR/issue-10291.rs:12:5
    |
+LL | fn test<'x>(x: &'x isize) {
+   |         -- lifetime `'x` defined here
 LL |     drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static`
 
index d5a67083a23b81ce60526ae512b5414ce1d13c75..a7e6c9f2b3371b7c54e40c88da02248888e1de7d 100644 (file)
@@ -5,7 +5,7 @@ LL |     let mut test = |foo: &Foo| {
    |                    ----------- mutable borrow occurs here
 LL |         println!("access {}", foo.x);
 LL |         ptr = box Foo { x: ptr.x + 1 };
-   |         --- previous borrow occurs due to use of `ptr` in closure
+   |         --- first borrow occurs due to use of `ptr` in closure
 ...
 LL |     test(&*ptr);
    |     -----^^^^^-
index f577aad04e620bf0c7e02bedb9ebdc60167a529c..ff6009da72fd96920bf3a2dd59d0fe5327b37783 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 fn main() {
-    print!(test!());
+    print!(testo!());
     //~^ ERROR: format argument must be a string literal
 }
index bee73e9f568b60e0e508cb3244a69d9cf16b52e0..61ff455d16ca587ec008a390b7fe470bfc8e5ea5 100644 (file)
@@ -1,11 +1,11 @@
 error: format argument must be a string literal
   --> $DIR/issue-11692-1.rs:12:12
    |
-LL |     print!(test!());
-   |            ^^^^^^^
+LL |     print!(testo!());
+   |            ^^^^^^^^
 help: you might be missing a string literal to format with
    |
-LL |     print!("{}", test!());
+LL |     print!("{}", testo!());
    |            ^^^^^
 
 error: aborting due to previous error
index acac2d151fe9ad5ef8008d3caf10f1a5de111bf7..c595b0fb2c2d8ea9d59f17f785153c7edd09190a 100644 (file)
@@ -10,5 +10,5 @@
 
 fn main() {
     concat!(test!());
-    //~^ ERROR cannot find macro `test!` in this scope
+    //~^ ERROR expected a macro, found non-macro attribute
 }
index 51d6041e92220e356b6f873a9ec54c9c8e5ca952..3d080bd46dcc967012c6a2a2a6b407519297f960 100644 (file)
@@ -1,4 +1,4 @@
-error: cannot find macro `test!` in this scope
+error: expected a macro, found non-macro attribute
   --> $DIR/issue-11692-2.rs:12:13
    |
 LL |     concat!(test!());
index c12cbbfdd53a16a4e0b3755ff9707f413d21ad3f..bf4fed06dee215faba00bfa586893ea5786e76c7 100644 (file)
@@ -2,7 +2,9 @@ error[E0505]: cannot move out of `v` because it is borrowed
   --> $DIR/issue-11873.rs:14:14
    |
 LL |     let mut f = || v.push(2);
-   |                 ------------ borrow of `v` occurs here
+   |                 -- - borrow occurs due to use in closure
+   |                 |
+   |                 borrow of `v` occurs here
 LL |     let _w = v; //~ ERROR: cannot move out of `v`
    |              ^ move out of `v` occurs here
 LL | 
index a040f7c3c8d1b04d336189a5348c5e9334ec572b..29bda252b9115f180495870e819928142669be9c 100644 (file)
@@ -3,28 +3,40 @@ error[E0508]: cannot move out of type `[T]`, a non-copy slice
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
+LL |         (&[], &[]) => println!("both empty"),
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 -- data moved here
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |                        --- ... and here
 help: to prevent move, use ref or ref mut
    |
 LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-   |                 ^^^^^^
-help: to prevent move, use ref or ref mut
-   |
+LL |             => println!("one empty"),
+LL |         //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+LL |         //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
 LL |         (&[hd1, ..], &[ref hd2, ..])
-   |                        ^^^^^^^
+   |
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
   --> $DIR/issue-12567.rs:14:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
+LL |         (&[], &[]) => println!("both empty"),
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 -- data moved here
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |            --- ... and here
 help: to prevent move, use ref or ref mut
    |
 LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-   |                 ^^^^^^
-help: to prevent move, use ref or ref mut
-   |
+LL |             => println!("one empty"),
+LL |         //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+LL |         //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
 LL |         (&[ref hd1, ..], &[hd2, ..])
-   |            ^^^^^^^
+   |
 
 error: aborting due to 2 previous errors
 
index 6bb7b4229d74739ff9d70cdb15a2306e7dea9492..8acdc73bf0e6867c0f44c8f7ad31a43b333f17ae 100644 (file)
@@ -2,11 +2,11 @@ error[E0499]: cannot borrow `y` as mutable more than once at a time
   --> $DIR/issue-18783.rs:17:21
    |
 LL |     c.push(Box::new(|| y = 0));
-   |                     -- - previous borrow occurs due to use of `y` in closure
+   |                     -- - first borrow occurs due to use of `y` in closure
    |                     |
    |                     first mutable borrow occurs here
 LL |     c.push(Box::new(|| y = 0));
-   |                     ^^ - borrow occurs due to use of `y` in closure
+   |                     ^^ - second borrow occurs due to use of `y` in closure
    |                     |
    |                     second mutable borrow occurs here
 LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time
@@ -17,11 +17,11 @@ error[E0499]: cannot borrow `y` as mutable more than once at a time
   --> $DIR/issue-18783.rs:26:29
    |
 LL |     Push::push(&c, Box::new(|| y = 0));
-   |                             -- - previous borrow occurs due to use of `y` in closure
+   |                             -- - first borrow occurs due to use of `y` in closure
    |                             |
    |                             first mutable borrow occurs here
 LL |     Push::push(&c, Box::new(|| y = 0));
-   |                             ^^ - borrow occurs due to use of `y` in closure
+   |                             ^^ - second borrow occurs due to use of `y` in closure
    |                             |
    |                             second mutable borrow occurs here
 LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time
index f601a6fbc88507582bc5ff2058541e9ed5d04932..e35f443548d90f8f75b2aff6a86cf35eb9bc7a6b 100644 (file)
@@ -2,7 +2,9 @@ error[E0382]: use of moved value: `x`
   --> $DIR/issue-24357.rs:16:12
    |
 LL |    let f = move || { let y = x; };
-   |            ---------------------- value moved here
+   |            -------           - variable moved due to use in closure
+   |            |
+   |            value moved into closure here
 LL |    //~^ NOTE value moved (into closure) here
 LL |    let z = x;
    |            ^ value used here after move
index d264bf8d2734df2146495a8e9120141e917f1603..91c51bcd0582502f20de9d41e8ebd434d9cc2a60 100644 (file)
@@ -1,11 +1,13 @@
 error[E0505]: cannot move out of `b` because it is borrowed
-  --> $DIR/issue-27282-move-match-input-into-guard.rs:26:16
+  --> $DIR/issue-27282-move-match-input-into-guard.rs:26:17
    |
 LL |     match b {
    |           - borrow of `b` occurs here
 LL |         &mut false => {},
 LL |         _ if { (|| { let bar = b; *bar = false; })();
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `b` occurs here
+   |                 ^^             - move occurs due to use in closure
+   |                 |
+   |                 move out of `b` occurs here
 ...
 LL |         &mut true => { println!("You might think we should get here"); },
    |         --------- borrow later used here
@@ -14,7 +16,9 @@ error[E0382]: use of moved value: `*b`
   --> $DIR/issue-27282-move-match-input-into-guard.rs:29:14
    |
 LL |         _ if { (|| { let bar = b; *bar = false; })();
-   |                ----------------------------------- value moved here
+   |                 --             - variable moved due to use in closure
+   |                 |
+   |                 value moved into closure here
 ...
 LL |         &mut true => { println!("You might think we should get here"); },
    |              ^^^^ value used here after move
index fb11090c222d073b570b60e1416726713a93e5b1..a9d9651fb2a35e45bfc89b600b2d642d19a62650 100644 (file)
@@ -5,7 +5,7 @@ LL |     match x {
    |           - borrow occurs here
 ...
 LL |             (|| { *x = None; drop(force_fn_once); })();
-   |              ^^    - borrow occurs due to use of `x` in closure
+   |              ^^    - second borrow occurs due to use of `x` in closure
    |              |
    |              closure construction occurs here
 ...
index 6e643d30185f9105ea9def4a08cc4645aec7f904..582d0fd678c07f56eb4d6f1d3a2caeec2de7ac20 100644 (file)
@@ -5,7 +5,7 @@ LL |     match x {
    |           - borrow occurs here
 ...
 LL |                 (|| { *x = None; drop(force_fn_once); })();
-   |                  ^^    - borrow occurs due to use of `x` in closure
+   |                  ^^    - second borrow occurs due to use of `x` in closure
    |                  |
    |                  closure construction occurs here
 ...
index 0b55117cad2ce782453eb0147d7f018654bcae2d..36a15e79ac825d5b872146eda6e2127ac78ad88a 100644 (file)
@@ -1,11 +1,3 @@
-error[E0597]: borrowed value does not live long enough
-  --> $DIR/issue-27592.rs:26:33
-   |
-LL |     write(|| format_args!("{}", String::from("Hello world")));
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here
-   |                                 |
-   |                                 temporary value does not live long enough
-
 error[E0597]: borrowed value does not live long enough
   --> $DIR/issue-27592.rs:26:27
    |
@@ -14,6 +6,14 @@ LL |     write(|| format_args!("{}", String::from("Hello world")));
    |                           |
    |                           temporary value does not live long enough
 
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-27592.rs:26:33
+   |
+LL |     write(|| format_args!("{}", String::from("Hello world")));
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here
+   |                                 |
+   |                                 temporary value does not live long enough
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0597`.
index 40d7838a8032519573159508158cdca96ab6305f..4ccd24fa4592141da4799057f4c26a3cc9978ccd 100644 (file)
@@ -5,10 +5,12 @@ LL |     id(Box::new(|| *v))
    |                    ^^ cannot move out of captured variable in an `FnMut` closure
 
 error[E0597]: `v` does not live long enough
-  --> $DIR/issue-4335.rs:16:17
+  --> $DIR/issue-4335.rs:16:21
    |
 LL |     id(Box::new(|| *v))
-   |                 ^^^^^ borrowed value does not live long enough
+   |                 --  ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL | }
    | - `v` dropped here while still borrowed
diff --git a/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs b/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs
new file mode 100644 (file)
index 0000000..881f37c
--- /dev/null
@@ -0,0 +1,133 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rust-lang/rust#45696: This test is checking that we can return
+// mutable borrows owned by boxes even when the boxes are dropped.
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// run-pass
+
+// This function shows quite directly what is going on: We have a
+// reborrow of contents within the box.
+fn return_borrow_from_dropped_box_1(x: Box<&mut u32>) -> &mut u32 { &mut **x }
+
+// This function is the way you'll probably see this in practice (the
+// reborrow is now implicit).
+fn return_borrow_from_dropped_box_2(x: Box<&mut u32>) -> &mut u32 { *x }
+
+// For the remaining tests we just add some fields or other
+// indirection to ensure that the compiler isn't just special-casing
+// the above `Box<&mut T>` as the only type that would work.
+
+// Here we add a tuple of indirection between the box and the
+// reference.
+type BoxedTup<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>;
+
+fn return_borrow_of_field_from_dropped_box_1<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
+    &mut *x.0
+}
+
+fn return_borrow_of_field_from_dropped_box_2<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
+    x.0
+}
+
+fn return_borrow_from_dropped_tupled_box_1<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
+    &mut *(x.0).0
+}
+
+fn return_borrow_from_dropped_tupled_box_2<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
+    (x.0).0
+}
+
+fn basic_tests() {
+    let mut x = 2;
+    let mut y = 3;
+    let mut z = 4;
+    *return_borrow_from_dropped_box_1(Box::new(&mut x)) += 10;
+    assert_eq!((x, y, z), (12, 3, 4));
+    *return_borrow_from_dropped_box_2(Box::new(&mut x)) += 10;
+    assert_eq!((x, y, z), (22, 3, 4));
+    *return_borrow_of_field_from_dropped_box_1(Box::new((&mut x, &mut y))) += 10;
+    assert_eq!((x, y, z), (32, 3, 4));
+    *return_borrow_of_field_from_dropped_box_2(Box::new((&mut x, &mut y))) += 10;
+    assert_eq!((x, y, z), (42, 3, 4));
+    *return_borrow_from_dropped_tupled_box_1((Box::new((&mut x, &mut y)), &mut z)) += 10;
+    assert_eq!((x, y, z), (52, 3, 4));
+    *return_borrow_from_dropped_tupled_box_2((Box::new((&mut x, &mut y)), &mut z)) += 10;
+    assert_eq!((x, y, z), (62, 3, 4));
+}
+
+// These scribbling tests have been transcribed from
+// issue-45696-scribble-on-boxed-borrow.rs
+//
+// In the context of that file, these tests are meant to show cases
+// that should be *accepted* by the compiler, so here we are actually
+// checking that the code we get when they are compiled matches our
+// expectations.
+
+struct Scribble<'a>(&'a mut u32);
+
+impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
+
+// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
+// to strictly outlive `'a`
+fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
+    &mut *s.0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
+    &mut *(*s).0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
+    &mut *(**s).0
+}
+
+fn scribbling_tests() {
+    let mut x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *borrowed_scribble(&mut long_lived) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+    x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+    x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+}
+
+fn main() {
+    basic_tests();
+    scribbling_tests();
+}
diff --git a/src/test/ui/issue-45696-no-variant-box-recur.rs b/src/test/ui/issue-45696-no-variant-box-recur.rs
new file mode 100644 (file)
index 0000000..da42e17
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rust-lang/rust#45696: This test checks the compiler won't infinite
+// loop when you declare a variable of type `struct A(Box<A>, ...);`
+// (which is impossible to construct but *is* possible to declare; see
+// also issues #4287, #44933, and #52852).
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// run-pass
+
+// This test has structs and functions that are by definiton unusable
+// all over the place, so just go ahead and allow dead_code
+#![allow(dead_code)]
+
+// direct regular recursion with indirect ownership via box
+struct C { field: Box<C> }
+
+// direct non-regular recursion with indirect ownership via box
+struct D { field: Box<(D, D)> }
+
+// indirect regular recursion with indirect ownership via box.
+struct E { field: F }
+struct F { field: Box<E> }
+
+// indirect non-regular recursion with indirect ownership via box.
+struct G { field: (H, H) }
+struct H { field: Box<G> }
+
+// These enums are cases that are not currently hit by the
+// `visit_terminator_drop` recursion down a type's structural
+// definition.
+//
+// But it seems prudent to include them in this test as variants on
+// the above, in that they are similarly non-constructable data types
+// with destructors that would diverge.
+enum I { One(Box<I>) }
+enum J { One(Box<J>), Two(Box<J>) }
+
+fn impossible_to_call_c(_c: C) { }
+fn impossible_to_call_d(_d: D) { }
+fn impossible_to_call_e(_e: E) { }
+fn impossible_to_call_f(_f: F) { }
+fn impossible_to_call_g(_g: G) { }
+fn impossible_to_call_h(_h: H) { }
+fn impossible_to_call_i(_i: I) { }
+fn impossible_to_call_j(_j: J) { }
+
+fn main() {
+
+}
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.ast.stderr b/src/test/ui/issue-45696-scribble-on-boxed-borrow.ast.stderr
new file mode 100644 (file)
index 0000000..6172a5e
--- /dev/null
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1
+   |
+LL | / fn main() { //[ast]~ ERROR compilation successful
+LL | |      //[migrate]~^ ERROR compilation successful
+LL | |     let mut x = 1;
+LL | |     {
+...  |
+LL | |     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issue-45696-scribble-on-boxed-borrow.migrate.stderr
new file mode 100644 (file)
index 0000000..da0dfac
--- /dev/null
@@ -0,0 +1,69 @@
+warning[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
+   |
+LL |     &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 62:14...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:14
+   |
+LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+   |              ^^
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+warning[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
+   |
+LL |     &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 72:20...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:72:20
+   |
+LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+   |                    ^^
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+warning[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5
+   |
+LL |     &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 82:26...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:26
+   |
+LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+   |                          ^^
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+error: compilation successful
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1
+   |
+LL | / fn main() { //[ast]~ ERROR compilation successful
+LL | |      //[migrate]~^ ERROR compilation successful
+LL | |     let mut x = 1;
+LL | |     {
+...  |
+LL | |     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.nll.stderr b/src/test/ui/issue-45696-scribble-on-boxed-borrow.nll.stderr
new file mode 100644 (file)
index 0000000..09cbc2f
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
+   |
+LL |     &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 62:14...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:14
+   |
+LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+   |              ^^
+
+error[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
+   |
+LL |     &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 72:20...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:72:20
+   |
+LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+   |                    ^^
+
+error[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5
+   |
+LL |     &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 82:26...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:26
+   |
+LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+   |                          ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.rs b/src/test/ui/issue-45696-scribble-on-boxed-borrow.rs
new file mode 100644 (file)
index 0000000..5a48742
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rust-lang/rust#45696: This test is checking that we *cannot* return
+// mutable borrows that would be scribbled over by destructors before
+// the return occurs.
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+// This test is going to pass in the ast and migrate revisions,
+// because the AST-borrowck accepted this code in the past (see notes
+// below). So we use `#[rustc_error]` to keep the outcome as an error
+// in all scenarios, and rely on the stderr files to show what the
+// actual behavior is. (See rust-lang/rust#49855.)
+#![feature(rustc_attrs)]
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+struct Scribble<'a>(&'a mut u32);
+
+impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
+
+// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
+// to strictly outlive `'a`
+fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
+    &mut *s.0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
+    &mut *(*s).0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
+    &mut *(**s).0
+}
+
+// this is not okay: in between the time that we take the mutable
+// borrow and the caller receives it as a return value, the drop of
+// `s` will scribble on it, violating our aliasing guarantees.
+//
+// * (Maybe in the future the two-phase borrows system will be
+//   extended to support this case. But for now, it is an error in
+//   NLL, even with two-phase borrows.)
+//
+// In any case, the AST-borrowck was not smart enough to know that
+// this should be an error. (Which is perhaps the essence of why
+// rust-lang/rust#45696 arose in the first place.)
+fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+    &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+    //[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
+    //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
+}
+
+// This, by analogy to previous case, is *also* not okay.
+//
+// (But again, AST-borrowck was not smart enogh to know that this
+// should be an error.)
+fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+    &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+    //[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
+    //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
+}
+
+// This, by analogy to previous case, is *also* not okay.
+//
+// (But again, AST-borrowck was not smart enogh to know that this
+// should be an error.)
+fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+    &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+    //[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
+    //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
+}
+
+#[rustc_error]
+fn main() { //[ast]~ ERROR compilation successful
+     //[migrate]~^ ERROR compilation successful
+    let mut x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *borrowed_scribble(&mut long_lived) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    *scribbled(Scribble(&mut x)) += 10;
+    *boxed_scribbled(Box::new(Scribble(&mut x))) += 10;
+    *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+}
diff --git a/src/test/ui/issue-49579.rs b/src/test/ui/issue-49579.rs
new file mode 100644 (file)
index 0000000..e4e97c5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// compile-pass
+
+#![feature(nll)]
+
+fn fibs(n: u32) -> impl Iterator<Item=u128> {
+    (0 .. n)
+    .scan((0, 1), |st, _| {
+        *st = (st.1, st.0 + st.1);
+        Some(*st)
+    })
+    .map(&|(f, _)| f)
+}
+
+fn main() {
+    println!("{:?}", fibs(10).collect::<Vec<_>>());
+}
diff --git a/src/test/ui/issue-49824.nll.stderr b/src/test/ui/issue-49824.nll.stderr
new file mode 100644 (file)
index 0000000..5934575
--- /dev/null
@@ -0,0 +1,20 @@
+error: unsatisfied lifetime constraints
+  --> $DIR/issue-49824.rs:22:9
+   |
+LL |         || {
+   |    _____-
+   |   |_____|
+   |  ||
+LL |  ||         || {
+   |  ||_________^
+LL | |||             let _y = &mut x;
+LL | |||         }
+   | |||_________^ requires that `'1` must outlive `'2`
+LL |  ||     };
+   |  ||     -
+   |  ||_____|
+   |  |______lifetime `'1` represents the closure body
+   |         lifetime `'2` appears in return type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-49824.rs b/src/test/ui/issue-49824.rs
new file mode 100644 (file)
index 0000000..1f3e575
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+// This test checks that a failure occurs with NLL but does not fail with the
+// legacy AST output. Check issue-49824.nll.stderr for expected compilation error
+// output under NLL and #49824 for more information.
+
+#[rustc_error]
+fn main() {
+    //~^ compilation successful
+    let mut x = 0;
+    || {
+        || {
+            let _y = &mut x;
+        }
+    };
+}
diff --git a/src/test/ui/issue-49824.stderr b/src/test/ui/issue-49824.stderr
new file mode 100644 (file)
index 0000000..b6cafe5
--- /dev/null
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-49824.rs:18:1
+   |
+LL | / fn main() {
+LL | |     //~^ compilation successful
+LL | |     let mut x = 0;
+LL | |     || {
+...  |
+LL | |     };
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index 87acf106393310c5f4799e63f4b977333a6ab239..ccb2742841cc5dd107a83a53bd598451d0a721ab 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-pass
 
-#![feature(use_extern_macros, decl_macro)]
+#![feature(decl_macro)]
 
 mod type_ns {
     pub type A = u8;
index ccbb852b1457484b78f384873994876c539a1f7b..e3e389d11970a886fc365debd5d2638600e6f3e7 100644 (file)
@@ -5,7 +5,7 @@ LL |         let v: Vec<&str> = line.split_whitespace().collect();
    |                            ^^^^ borrowed value does not live long enough
 LL |         //~^ ERROR `line` does not live long enough
 LL |         println!("accumulator before add_assign {:?}", acc.map);
-   |                                                        ------- borrow later used here
+   |                                                        ------- borrow used here in later iteration of loop
 ...
 LL |     }
    |     - `line` dropped here while still borrowed
index 7dd513d1b712c2e31fd8a016664b021fb3ff114c..4e1efc96490bd718e8641bbda2b75ea008baf8ad 100644 (file)
@@ -7,6 +7,11 @@ LL |     match (&t,) { //~ ERROR cannot infer an appropriate lifetime
 error: unsatisfied lifetime constraints
   --> $DIR/issue-52213.rs:13:11
    |
+LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
+   |                       --  -- lifetime `'b` defined here
+   |                       |
+   |                       lifetime `'a` defined here
+LL |     match (&t,) { //~ ERROR cannot infer an appropriate lifetime
 LL |         ((u,),) => u,
    |           ^ requires that `'a` must outlive `'b`
 
index 5436397c68eada02a3632af12ff0fb7a3392cb94..3ca2f39470da7a9471329906606684029a327c01 100644 (file)
@@ -2,7 +2,9 @@ error[E0505]: cannot move out of `x` because it is borrowed
   --> $DIR/issue-6801.rs:29:13
    |
 LL |       let sq =  || { *x * *x };
-   |                 -------------- borrow of `x` occurs here
+   |                 --    - borrow occurs due to use in closure
+   |                 |
+   |                 borrow of `x` occurs here
 LL | 
 LL |       twice(x); //~ ERROR: cannot move out of
    |             ^ move out of `x` occurs here
index 2ec0111ff4b66e4ee423c3b8eb697ca69c920f2b..2a9bd2948ffeb4fbe96302fe80957a6d4ddf7632 100644 (file)
@@ -82,7 +82,7 @@
           ],
           "label": null,
           "suggested_replacement": "1 / (2 + 3)",
-          "suggestion_applicability": "Unspecified",
+          "suggestion_applicability": "MachineApplicable",
           "expansion": null
         }
       ],
diff --git a/src/test/ui/macro-path-prelude-fail-1.rs b/src/test/ui/macro-path-prelude-fail-1.rs
new file mode 100644 (file)
index 0000000..b953805
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros, extern_prelude)]
+
+mod m {
+    fn check() {
+        Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec`
+        u8::clone!(); //~ ERROR failed to resolve. Not a module `u8`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-fail-1.stderr b/src/test/ui/macro-path-prelude-fail-1.stderr
new file mode 100644 (file)
index 0000000..fc74937
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve. Not a module `Vec`
+  --> $DIR/macro-path-prelude-fail-1.rs:15:9
+   |
+LL |         Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec`
+   |         ^^^ Not a module `Vec`
+
+error[E0433]: failed to resolve. Not a module `u8`
+  --> $DIR/macro-path-prelude-fail-1.rs:16:9
+   |
+LL |         u8::clone!(); //~ ERROR failed to resolve. Not a module `u8`
+   |         ^^ Not a module `u8`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macro-path-prelude-fail-2.rs b/src/test/ui/macro-path-prelude-fail-2.rs
new file mode 100644 (file)
index 0000000..ec77e27
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros)]
+
+mod m {
+    fn check() {
+        Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-fail-2.stderr b/src/test/ui/macro-path-prelude-fail-2.stderr
new file mode 100644 (file)
index 0000000..d23aed8
--- /dev/null
@@ -0,0 +1,8 @@
+error: fail to resolve non-ident macro path
+  --> $DIR/macro-path-prelude-fail-2.rs:15:9
+   |
+LL |         Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macro-path-prelude-fail-3.rs b/src/test/ui/macro-path-prelude-fail-3.rs
new file mode 100644 (file)
index 0000000..4cf9001
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros)]
+
+#[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
+struct S;
+
+fn main() {
+    inline!(); //~ ERROR expected a macro, found non-macro attribute
+}
diff --git a/src/test/ui/macro-path-prelude-fail-3.stderr b/src/test/ui/macro-path-prelude-fail-3.stderr
new file mode 100644 (file)
index 0000000..bd1015b
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected a macro, found non-macro attribute
+  --> $DIR/macro-path-prelude-fail-3.rs:13:10
+   |
+LL | #[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
+   |          ^^^^^^
+
+error: expected a macro, found non-macro attribute
+  --> $DIR/macro-path-prelude-fail-3.rs:17:5
+   |
+LL |     inline!(); //~ ERROR expected a macro, found non-macro attribute
+   |     ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macro-path-prelude-pass.rs b/src/test/ui/macro-path-prelude-pass.rs
new file mode 100644 (file)
index 0000000..bc58754
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(use_extern_macros, extern_prelude)]
+
+mod m {
+    fn check() {
+        std::panic!(); // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-shadowing.rs b/src/test/ui/macro-path-prelude-shadowing.rs
new file mode 100644 (file)
index 0000000..1aff777
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro-in-other-crate.rs
+
+#![feature(decl_macro, extern_prelude)]
+
+macro_rules! add_macro_expanded_things_to_macro_prelude {() => {
+    #[macro_use]
+    extern crate macro_in_other_crate;
+}}
+
+add_macro_expanded_things_to_macro_prelude!();
+
+mod m1 {
+    fn check() {
+        inline!(); //~ ERROR `inline` is ambiguous
+    }
+}
+
+mod m2 {
+    pub mod std {
+        pub macro panic() {}
+    }
+}
+
+mod m3 {
+    use m2::*; // glob-import user-defined `std`
+    fn check() {
+        std::panic!(); //~ ERROR `std` is ambiguous
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-shadowing.stderr b/src/test/ui/macro-path-prelude-shadowing.stderr
new file mode 100644 (file)
index 0000000..0e1b9a9
--- /dev/null
@@ -0,0 +1,42 @@
+error[E0659]: `inline` is ambiguous
+  --> $DIR/macro-path-prelude-shadowing.rs:24:9
+   |
+LL |         inline!(); //~ ERROR `inline` is ambiguous
+   |         ^^^^^^
+   |
+note: `inline` could refer to the name imported here
+  --> $DIR/macro-path-prelude-shadowing.rs:16:5
+   |
+LL |     #[macro_use]
+   |     ^^^^^^^^^^^^
+...
+LL | add_macro_expanded_things_to_macro_prelude!();
+   | ---------------------------------------------- in this macro invocation
+note: `inline` could also refer to the name defined here
+  --> $DIR/macro-path-prelude-shadowing.rs:24:9
+   |
+LL |         inline!(); //~ ERROR `inline` is ambiguous
+   |         ^^^^^^
+   = note: macro-expanded macro imports do not shadow
+
+error[E0659]: `std` is ambiguous
+  --> $DIR/macro-path-prelude-shadowing.rs:37:9
+   |
+LL |         std::panic!(); //~ ERROR `std` is ambiguous
+   |         ^^^^^^^^^^
+   |
+note: `std` could refer to the name imported here
+  --> $DIR/macro-path-prelude-shadowing.rs:35:9
+   |
+LL |     use m2::*; // glob-import user-defined `std`
+   |         ^^^^^
+note: `std` could also refer to the name defined here
+  --> $DIR/macro-path-prelude-shadowing.rs:37:9
+   |
+LL |         std::panic!(); //~ ERROR `std` is ambiguous
+   |         ^^^
+   = note: consider adding an explicit import of `std` to disambiguate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
index 33401424c9ada42cce9be51c6bc30d09e617e7fb..ac00ce3af9624dcef68b92bff544d83dd86efdaa 100644 (file)
@@ -22,4 +22,6 @@ fn main() {
     println!("{} %f", "one", 2.0); //~ ERROR never used
 
     println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used
+    println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
+    //~^ ERROR multiple unused formatting arguments
 }
index 5e76c0a322e51b941296762b1e793191c4112ba8..d5e2b514c405c09994d34f0ae875cb72795d40d1 100644 (file)
@@ -52,10 +52,25 @@ error: named argument never used
   --> $DIR/format-foreign.rs:24:39
    |
 LL |     println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used
-   |                                       ^^^^^
+   |                         -----         ^^^^^
+   |                         |
+   |                         help: format specifiers use curly braces: `{NAME}`
    |
-   = help: `$NAME` should be written as `{NAME}`
    = note: shell formatting not supported; see the documentation for `std::fmt`
 
-error: aborting due to 5 previous errors
+error: multiple unused formatting arguments
+  --> $DIR/format-foreign.rs:25:32
+   |
+LL |     println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
+   |              ----------------  ^  ^       ^
+   |              |
+   |              multiple missing formatting specifiers
+   |
+   = note: shell formatting not supported; see the documentation for `std::fmt`
+help: format specifiers use curly braces
+   |
+LL |     println!("{1} {0} $$ {NAME}", 1, 2, NAME=3);
+   |               ^^^ ^^^    ^^^^^^
+
+error: aborting due to 6 previous errors
 
index 81171a1ed01de5dfe035f8ab353e727ba8b2300a..67ffeec67cc8b05f8e83190e96dc8c761b1e152c 100644 (file)
@@ -30,7 +30,10 @@ error: multiple unused formatting arguments
   --> $DIR/format-unused-lables.rs:24:9
    |
 LL |     println!("Some more $STUFF",
-   |              ------------------ multiple missing formatting specifiers
+   |              ------------------
+   |              |          |
+   |              |          help: format specifiers use curly braces: `{STUFF}`
+   |              multiple missing formatting specifiers
 LL |         "woo!",  //~ ERROR multiple unused formatting arguments
    |         ^^^^^^
 LL |             STUFF=
@@ -39,7 +42,6 @@ LL |        "things"
 LL |              , UNUSED="args");
    |                       ^^^^^^
    |
-   = help: `$STUFF` should be written as `{STUFF}`
    = note: shell formatting not supported; see the documentation for `std::fmt`
 
 error: aborting due to 4 previous errors
index 2a30d9837517e2dcd42f805328e4b8683246afb7..4b716ff27446af9b000f699ff4928eb3a80f5240 100644 (file)
@@ -5,8 +5,5 @@ LL |     println!("Hello, World!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `println! { "Hello, World!" }`
-   = note: to `{
-           # [ cfg ( not ( stage0 ) ) ] {
-           ( $crate :: io :: _print ( format_args_nl ! ( "Hello, World!" ) ) ) ; } # [
-           cfg ( stage0 ) ] { print ! ( "{}/n" , format_args ! ( "Hello, World!" ) ) } }`
+   = note: to `{ $crate :: io :: _print ( format_args_nl ! ( "Hello, World!" ) ) ; }`
 
diff --git a/src/test/ui/nll/closure-access-spans.rs b/src/test/ui/nll/closure-access-spans.rs
new file mode 100644 (file)
index 0000000..b49436f
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that accesses due to a closure capture give a special note
+
+#![feature(nll)]
+
+fn closure_imm_capture_conflict(mut x: i32) {
+    let r = &mut x;
+    || x; //~ ERROR
+    r.use_mut();
+}
+
+fn closure_mut_capture_conflict(mut x: i32) {
+    let r = &mut x;
+    || x = 2; //~ ERROR
+    r.use_mut();
+}
+
+fn closure_unique_capture_conflict(mut x: &mut i32) {
+    let r = &mut x;
+    || *x = 2; //~ ERROR
+    r.use_mut();
+}
+
+fn closure_copy_capture_conflict(mut x: i32) {
+    let r = &mut x;
+    move || x; //~ ERROR
+    r.use_ref();
+}
+
+fn closure_move_capture_conflict(mut x: String) {
+    let r = &x;
+    || x; //~ ERROR
+    r.use_ref();
+}
+
+fn closure_imm_capture_moved(mut x: String) {
+    let r = x;
+    || x.len(); //~ ERROR
+}
+
+fn closure_mut_capture_moved(mut x: String) {
+    let r = x;
+    || x = String::new(); //~ ERROR
+}
+
+fn closure_unique_capture_moved(x: &mut String) {
+    let r = x;
+    || *x = String::new(); //~ ERROR
+}
+
+fn closure_move_capture_moved(x: &mut String) {
+    let r = x;
+    || x; //~ ERROR
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr
new file mode 100644 (file)
index 0000000..0042b5d
--- /dev/null
@@ -0,0 +1,110 @@
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/closure-access-spans.rs:17:5
+   |
+LL |     let r = &mut x;
+   |             ------ mutable borrow occurs here
+LL |     || x; //~ ERROR
+   |     ^^ - second borrow occurs due to use of `x` in closure
+   |     |
+   |     immutable borrow occurs here
+LL |     r.use_mut();
+   |     - borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/closure-access-spans.rs:23:5
+   |
+LL |     let r = &mut x;
+   |             ------ first mutable borrow occurs here
+LL |     || x = 2; //~ ERROR
+   |     ^^ - second borrow occurs due to use of `x` in closure
+   |     |
+   |     second mutable borrow occurs here
+LL |     r.use_mut();
+   |     - borrow later used here
+
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/closure-access-spans.rs:29:5
+   |
+LL |     let r = &mut x;
+   |             ------ borrow occurs here
+LL |     || *x = 2; //~ ERROR
+   |     ^^  - second borrow occurs due to use of `x` in closure
+   |     |
+   |     closure construction occurs here
+LL |     r.use_mut();
+   |     - borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/closure-access-spans.rs:35:13
+   |
+LL |     let r = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     move || x; //~ ERROR
+   |             ^ use of borrowed `x`
+LL |     r.use_ref();
+   |     - borrow later used here
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/closure-access-spans.rs:41:5
+   |
+LL |     let r = &x;
+   |             -- borrow of `x` occurs here
+LL |     || x; //~ ERROR
+   |     ^^ - move occurs due to use in closure
+   |     |
+   |     move out of `x` occurs here
+LL |     r.use_ref();
+   |     - borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-access-spans.rs:47:5
+   |
+LL |     let r = x;
+   |             - value moved here
+LL |     || x.len(); //~ ERROR
+   |     ^^ - borrow occurs due to use in closure
+   |     |
+   |     value borrowed here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-access-spans.rs:52:5
+   |
+LL |     let r = x;
+   |             - value moved here
+LL |     || x = String::new(); //~ ERROR
+   |     ^^ - borrow occurs due to use in closure
+   |     |
+   |     value borrowed here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-access-spans.rs:57:5
+   |
+LL |     let r = x;
+   |             - value moved here
+LL |     || *x = String::new(); //~ ERROR
+   |     ^^  - borrow occurs due to use in closure
+   |     |
+   |     value borrowed here after move
+   |
+   = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/closure-access-spans.rs:62:5
+   |
+LL |     let r = x;
+   |             - value moved here
+LL |     || x; //~ ERROR
+   |     ^^ - use occurs due to use in closure
+   |     |
+   |     value used here after move
+   |
+   = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0382, E0499, E0500, E0502, E0503, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/closure-borrow-spans.rs b/src/test/ui/nll/closure-borrow-spans.rs
new file mode 100644 (file)
index 0000000..d62dc27
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that existing borrows due to a closure capture give a special note
+
+#![feature(nll)]
+
+fn move_while_borrowed(x: String) {
+    let f = || x.len();
+    let y = x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_mut_while_borrowed(mut x: i32) {
+    let f = || x;
+    let y = &mut x; //~ ERROR
+    f.use_ref();
+}
+
+fn drop_while_borrowed() {
+    let f;
+    {
+        let x = 1;
+        f = || x; //~ ERROR
+    }
+    f.use_ref();
+}
+
+fn assign_while_borrowed(mut x: i32) {
+    let f = || x;
+    x = 1; //~ ERROR
+    f.use_ref();
+}
+
+fn copy_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    let y = x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    let y = &x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_mut_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    let y = &mut x; //~ ERROR
+    f.use_ref();
+}
+
+fn drop_while_borrowed_mut() {
+    let f;
+    {
+        let mut x = 1;
+        f = || x = 0; //~ ERROR
+    }
+    f.use_ref();
+}
+
+fn assign_while_borrowed_mut(mut x: i32) {
+    let f = || x = 0;
+    x = 1; //~ ERROR
+    f.use_ref();
+}
+
+fn copy_while_borrowed_unique(x: &mut i32) {
+    let f = || *x = 0;
+    let y = x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_while_borrowed_unique(x: &mut i32) {
+    let f = || *x = 0;
+    let y = &x; //~ ERROR
+    f.use_ref();
+}
+
+fn borrow_mut_while_borrowed_unique(mut x: &mut i32) {
+    let f = || *x = 0;
+    let y = &mut x; //~ ERROR
+    f.use_ref();
+}
+
+fn drop_while_borrowed_unique() {
+    let mut z = 1;
+    let f;
+    {
+        let x = &mut z;
+        f = || *x = 0; //~ ERROR
+    }
+    f.use_ref();
+}
+
+fn assign_while_borrowed_unique(x: &mut i32) {
+    let f = || *x = 0;
+    *x = 1; //~ ERROR
+    f.use_ref();
+}
+
+fn main() {}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr
new file mode 100644 (file)
index 0000000..1b9420b
--- /dev/null
@@ -0,0 +1,172 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:17:13
+   |
+LL |     let f = || x.len();
+   |             -- - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let y = x; //~ ERROR
+   |             ^ move out of `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/closure-borrow-spans.rs:23:13
+   |
+LL |     let f = || x;
+   |             -- - first borrow occurs due to use of `x` in closure
+   |             |
+   |             immutable borrow occurs here
+LL |     let y = &mut x; //~ ERROR
+   |             ^^^^^^ mutable borrow occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/closure-borrow-spans.rs:31:16
+   |
+LL |         f = || x; //~ ERROR
+   |             -- ^ borrowed value does not live long enough
+   |             |
+   |             value captured here
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:38:5
+   |
+LL |     let f = || x;
+   |             -- - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     x = 1; //~ ERROR
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/closure-borrow-spans.rs:44:13
+   |
+LL |     let f = || x = 0;
+   |             -- - borrow occurs due to use of `x` in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let y = x; //~ ERROR
+   |             ^ use of borrowed `x`
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/closure-borrow-spans.rs:50:13
+   |
+LL |     let f = || x = 0;
+   |             -- - first borrow occurs due to use of `x` in closure
+   |             |
+   |             mutable borrow occurs here
+LL |     let y = &x; //~ ERROR
+   |             ^^ immutable borrow occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/closure-borrow-spans.rs:56:13
+   |
+LL |     let f = || x = 0;
+   |             -- - first borrow occurs due to use of `x` in closure
+   |             |
+   |             first mutable borrow occurs here
+LL |     let y = &mut x; //~ ERROR
+   |             ^^^^^^ second mutable borrow occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/closure-borrow-spans.rs:64:16
+   |
+LL |         f = || x = 0; //~ ERROR
+   |             -- ^ borrowed value does not live long enough
+   |             |
+   |             value captured here
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:71:5
+   |
+LL |     let f = || x = 0;
+   |             -- - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     x = 1; //~ ERROR
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:77:13
+   |
+LL |     let f = || *x = 0;
+   |             --  - borrow occurs due to use in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let y = x; //~ ERROR
+   |             ^ move out of `x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
+  --> $DIR/closure-borrow-spans.rs:83:13
+   |
+LL |     let f = || *x = 0;
+   |             --  - first borrow occurs due to use of `x` in closure
+   |             |
+   |             closure construction occurs here
+LL |     let y = &x; //~ ERROR
+   |             ^^ borrow occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access
+  --> $DIR/closure-borrow-spans.rs:89:13
+   |
+LL |     let f = || *x = 0;
+   |             --  - first borrow occurs due to use of `x` in closure
+   |             |
+   |             closure construction occurs here
+LL |     let y = &mut x; //~ ERROR
+   |             ^^^^^^ borrow occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/closure-borrow-spans.rs:98:17
+   |
+LL |         f = || *x = 0; //~ ERROR
+   |             --  ^ borrowed value does not live long enough
+   |             |
+   |             value captured here
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+  --> $DIR/closure-borrow-spans.rs:105:5
+   |
+LL |     let f = || *x = 0;
+   |             --  - borrow occurs due to use in closure
+   |             |
+   |             borrow of `*x` occurs here
+LL |     *x = 1; //~ ERROR
+   |     ^^^^^^ assignment to borrowed `*x` occurs here
+LL |     f.use_ref();
+   |     - borrow later used here
+
+error: aborting due to 14 previous errors
+
+Some errors occurred: E0499, E0501, E0502, E0503, E0505, E0506, E0597.
+For more information about an error, try `rustc --explain E0499`.
index 03a22bb79a86ba527831c62b94c634a8dc664952..16385ca2499cc46f81c49130009fe706faec94a2 100644 (file)
@@ -13,7 +13,7 @@
 #![allow(unused)]
 #![feature(nll)]
 
-// Should have one error per assigment
+// Should have one error per assignment
 
 fn one_closure(x: i32) {
     ||
diff --git a/src/test/ui/nll/closure-move-spans.rs b/src/test/ui/nll/closure-move-spans.rs
new file mode 100644 (file)
index 0000000..7e83627
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that moves due to a closure capture give a special note
+
+#![feature(nll)]
+
+fn move_after_move(x: String) {
+    || x;
+    let y = x; //~ ERROR
+}
+
+fn borrow_after_move(x: String) {
+    || x;
+    let y = &x; //~ ERROR
+}
+
+fn borrow_mut_after_move(mut x: String) {
+    || x;
+    let y = &mut x; //~ ERROR
+}
+
+fn fn_ref<F: Fn()>(f: F) -> F { f }
+fn fn_mut<F: FnMut()>(f: F) -> F { f }
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-move-spans.stderr b/src/test/ui/nll/closure-move-spans.stderr
new file mode 100644 (file)
index 0000000..80b7b42
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/closure-move-spans.rs:17:13
+   |
+LL |     || x;
+   |     -- - variable moved due to use in closure
+   |     |
+   |     value moved into closure here
+LL |     let y = x; //~ ERROR
+   |             ^ value used here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-move-spans.rs:22:13
+   |
+LL |     || x;
+   |     -- - variable moved due to use in closure
+   |     |
+   |     value moved into closure here
+LL |     let y = &x; //~ ERROR
+   |             ^^ value borrowed here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/closure-move-spans.rs:27:13
+   |
+LL |     || x;
+   |     -- - variable moved due to use in closure
+   |     |
+   |     value moved into closure here
+LL |     let y = &mut x; //~ ERROR
+   |             ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
index ccf116e640d429ec4fed4e09a447664a93a65af5..862d1f0b179c0e34a9e412ede8be5fe019efc35a 100644 (file)
@@ -4,15 +4,6 @@ warning: not reporting region error due to nll
 LL |         let mut closure = expect_sig(|p, y| *p = y);
    |                                                  ^
 
-error: unsatisfied lifetime constraints
-  --> $DIR/escape-argument-callee.rs:36:45
-   |
-LL |         let mut closure = expect_sig(|p, y| *p = y);
-   |                                       -  -  ^^^^^^ requires that `'1` must outlive `'2`
-   |                                       |  |
-   |                                       |  has type `&'1 i32`
-   |                                       has type `&mut &'2 i32`
-
 note: No external requirements
   --> $DIR/escape-argument-callee.rs:36:38
    |
@@ -24,6 +15,15 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
                for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32))
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/escape-argument-callee.rs:36:45
+   |
+LL |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                       -  -  ^^^^^^ requires that `'1` must outlive `'2`
+   |                                       |  |
+   |                                       |  has type `&'1 i32`
+   |                                       has type `&mut &'2 i32`
+
 note: No external requirements
   --> $DIR/escape-argument-callee.rs:30:1
    |
index 598839f872e01805bc1d896c3f6755754cdc8500..ce44903e6e6a84505b32f849b6d670f03a2503f3 100644 (file)
@@ -27,8 +27,8 @@ fn test() {
     {
         let y = 22;
 
-        let mut closure = || { //~ ERROR `y` does not live long enough [E0597]
-            let mut closure1 = || p = &y;
+        let mut closure = || {
+            let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597]
             closure1();
         };
 
index bf12800e58d71ffbcc4679f56e7e9cf8fa6a23d8..ed2ae2f27b57b643e596f79c6cda6dbdb18db594 100644 (file)
@@ -1,7 +1,7 @@
 note: External requirements
   --> $DIR/escape-upvar-nested.rs:31:32
    |
-LL |             let mut closure1 = || p = &y;
+LL |             let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597]
    |                                ^^^^^^^^^
    |
    = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [
@@ -16,9 +16,9 @@ LL |             let mut closure1 = || p = &y;
 note: External requirements
   --> $DIR/escape-upvar-nested.rs:30:27
    |
-LL |           let mut closure = || { //~ ERROR `y` does not live long enough [E0597]
+LL |           let mut closure = || {
    |  ___________________________^
-LL | |             let mut closure1 = || p = &y;
+LL | |             let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597]
 LL | |             closure1();
 LL | |         };
    | |_________^
@@ -47,20 +47,18 @@ LL | | }
    = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs []
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/escape-upvar-nested.rs:30:27
+  --> $DIR/escape-upvar-nested.rs:31:40
    |
-LL |           let mut closure = || { //~ ERROR `y` does not live long enough [E0597]
-   |  ___________________________^
-LL | |             let mut closure1 = || p = &y;
-LL | |             closure1();
-LL | |         };
-   | |_________^ borrowed value does not live long enough
+LL |         let mut closure = || {
+   |                           -- value captured here
+LL |             let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597]
+   |                                        ^ borrowed value does not live long enough
 ...
-LL |       }
-   |       - `y` dropped here while still borrowed
+LL |     }
+   |     - `y` dropped here while still borrowed
 LL | 
-LL |       deref(p);
-   |             - borrow later used here
+LL |     deref(p);
+   |           - borrow later used here
 
 error: aborting due to previous error
 
index 4b0dad3bda0229c93083e54301c77666ffe15a3d..8db56deeb1f7ae83dbb4482708fa314d7ec1dba0 100644 (file)
@@ -28,10 +28,12 @@ LL | | }
    = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs []
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/escape-upvar-ref.rs:33:27
+  --> $DIR/escape-upvar-ref.rs:33:35
    |
 LL |         let mut closure = || p = &y;
-   |                           ^^^^^^^^^ borrowed value does not live long enough
+   |                           --      ^ borrowed value does not live long enough
+   |                           |
+   |                           value captured here
 ...
 LL |     }
    |     - `y` dropped here while still borrowed
index b4508824901952cf390beed9727c9cc355285330..72b7104b99dd3c5a3dcb0d4ebc155d8de5adfcb4 100644 (file)
@@ -4,17 +4,6 @@ warning: not reporting region error due to nll
 LL |             let p = x.get();
    |                     ^^^^^^^
 
-error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
-   |
-LL |         |_outlives1, _outlives2, _outlives3, x, y| {
-   |          ----------              ---------- has type `std::cell::Cell<&'2 &u32>`
-   |          |
-   |          has type `std::cell::Cell<&&'1 u32>`
-...
-LL |             demand_y(x, y, p) //~ ERROR
-   |             ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
-
 note: No external requirements
   --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9
    |
@@ -31,6 +20,17 @@ LL | |         },
                for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
+   |
+LL |         |_outlives1, _outlives2, _outlives3, x, y| {
+   |          ----------              ---------- has type `std::cell::Cell<&'2 &u32>`
+   |          |
+   |          has type `std::cell::Cell<&&'1 u32>`
+...
+LL |             demand_y(x, y, p) //~ ERROR
+   |             ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+
 note: No external requirements
   --> $DIR/propagate-approximated-fail-no-postdom.rs:48:1
    |
index a3588ff07e6a50c6151f0ba355590eb7fc84d667..43c39dee2448a1c5793579421402015233dd34b2 100644 (file)
@@ -4,17 +4,6 @@ warning: not reporting region error due to nll
 LL |     foo(cell, |cell_a, cell_x| {
    |     ^^^
 
-error: borrowed data escapes outside of closure
-  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
-   |
-LL |     foo(cell, |cell_a, cell_x| {
-   |                ------  ------ `cell_x` is a reference that is only valid in the closure body
-   |                |
-   |                `cell_a` is declared here, outside of the closure body
-LL |         //~^ WARNING not reporting region error due to nll
-LL |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
-
 note: No external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15
    |
@@ -31,6 +20,17 @@ LL | |     })
                for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
            ]
 
+error: borrowed data escapes outside of closure
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
+   |
+LL |     foo(cell, |cell_a, cell_x| {
+   |                ------  ------ `cell_x` is a reference that is only valid in the closure body
+   |                |
+   |                `cell_a` is declared here, outside of the closure body
+LL |         //~^ WARNING not reporting region error due to nll
+LL |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
+
 note: No external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1
    |
index d5495b69c7ced1ef761b21d8f74d06e0fa498e16..c3bbf1035dbc574081c9d1a7d093606a5c1b54fa 100644 (file)
@@ -23,19 +23,6 @@ LL | |     });
    = note: number of external vids: 4
    = note: where '_#1r: '_#0r
 
-error: borrowed data escapes outside of function
-  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5
-   |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |                     ------ `cell_a` is a reference that is only valid in the function body
-LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-LL | |         //~^ ERROR
-LL | |
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
-LL | |     });
-   | |______^ `cell_a` escapes the function body here
-
 note: No external requirements
   --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1
    |
@@ -50,5 +37,18 @@ LL | | }
    |
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs []
 
+error: borrowed data escapes outside of function
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5
+   |
+LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |                     ------ `cell_a` is a reference that is only valid in the function body
+LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+LL | |         //~^ ERROR
+LL | |
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
+LL | |     });
+   | |______^ `cell_a` escapes the function body here
+
 error: aborting due to previous error
 
index 50e2dd23da8a88e5527ebeeb86fe3a99ce86c7aa..9f259e2dee5904616ae14b850d277e817d93f8d6 100644 (file)
@@ -23,19 +23,6 @@ LL | |     });
    = note: number of external vids: 5
    = note: where '_#1r: '_#0r
 
-error: borrowed data escapes outside of function
-  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5
-   |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |                     ------ `cell_a` is a reference that is only valid in the function body
-LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-LL | |         //~^ ERROR
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
-LL | |         //~^ WARNING not reporting region error due to nll
-LL | |     });
-   | |______^ `cell_a` escapes the function body here
-
 note: No external requirements
   --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1
    |
@@ -50,5 +37,18 @@ LL | | }
    |
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs []
 
+error: borrowed data escapes outside of function
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5
+   |
+LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |                     ------ `cell_a` is a reference that is only valid in the function body
+LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+LL | |         //~^ ERROR
+LL | |         // Only works if 'x: 'y:
+LL | |         demand_y(x, y, x.get())
+LL | |         //~^ WARNING not reporting region error due to nll
+LL | |     });
+   | |______^ `cell_a` escapes the function body here
+
 error: aborting due to previous error
 
index 40ebda4419b2a09aa07d3d7331692ea47c501feb..cd5e6f29f5f480cc2862f714777b826c80527414 100644 (file)
@@ -4,17 +4,6 @@ warning: not reporting region error due to nll
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unsatisfied lifetime constraints
-  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
-   |
-LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-   |                                                ---------  - has type `&std::cell::Cell<&'1 u32>`
-   |                                                |
-   |                                                has type `&std::cell::Cell<&'2 &u32>`
-LL |         // Only works if 'x: 'y:
-LL |         demand_y(x, y, x.get())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
-
 note: No external requirements
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47
    |
@@ -32,6 +21,17 @@ LL | |     });
                for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
+   |
+LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |                                                ---------  - has type `&std::cell::Cell<&'1 u32>`
+   |                                                |
+   |                                                has type `&std::cell::Cell<&'2 &u32>`
+LL |         // Only works if 'x: 'y:
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+
 note: No external requirements
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:44:1
    |
index 37ea610397696823dc08c790414d86326b211735..2176575e0aa128e7067afdad22b870fd0edbcc80 100644 (file)
@@ -4,17 +4,6 @@ warning: not reporting region error due to nll
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unsatisfied lifetime constraints
-  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
-   |
-LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-   |                                                ----------  ---------- has type `&std::cell::Cell<&'2 &u32>`
-   |                                                |
-   |                                                has type `&std::cell::Cell<&'1 &u32>`
-LL |         // Only works if 'x: 'y:
-LL |         demand_y(x, y, x.get())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
-
 note: No external requirements
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47
    |
@@ -32,6 +21,17 @@ LL | |     });
                for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
+   |
+LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |                                                ----------  ---------- has type `&std::cell::Cell<&'2 &u32>`
+   |                                                |
+   |                                                has type `&std::cell::Cell<&'1 &u32>`
+LL |         // Only works if 'x: 'y:
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+
 note: No external requirements
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:48:1
    |
index 42d5b15bd5a29d7c460d88a2c312159e0cdefa5d..8f8a99df5f0529dcef540ee13de8b348d85d654b 100644 (file)
@@ -26,21 +26,6 @@ LL | |     });
    = note: number of external vids: 3
    = note: where T: '_#1r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/propagate-from-trait-match.rs:42:36
-   |
-LL |       establish_relationships(value, |value| {
-   |  ____________________________________^
-LL | |         //~^ ERROR the parameter type `T` may not live long enough
-LL | |
-LL | |         // This function call requires that
-...  |
-LL | |         //~^ WARNING not reporting region error due to nll
-LL | |     });
-   | |_____^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
-
 note: No external requirements
   --> $DIR/propagate-from-trait-match.rs:38:1
    |
@@ -58,6 +43,21 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/propagate-from-trait-match.rs:42:36
+   |
+LL |       establish_relationships(value, |value| {
+   |  ____________________________________^
+LL | |         //~^ ERROR the parameter type `T` may not live long enough
+LL | |
+LL | |         // This function call requires that
+...  |
+LL | |         //~^ WARNING not reporting region error due to nll
+LL | |     });
+   | |_____^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0309`.
index b0562711627387d59157493727b9bfe0681f784d..116ff6ef023561e0ddb121071585b1ed92baac7c 100644 (file)
@@ -7,6 +7,8 @@ LL |     &*x
 error: unsatisfied lifetime constraints
   --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
    |
+LL | fn foo<'a>(x: &'a u32) -> &'static u32 {
+   |        -- lifetime `'a` defined here
 LL |     &*x
    |     ^^^ requires that `'a` must outlive `'static`
 
index d6d1645ceeacc755a3b727c34dd40171d4a0019b..d2e088815e11803a83f08dea0767f7904ade647c 100644 (file)
@@ -4,15 +4,6 @@ warning: not reporting region error due to nll
 LL |     expect_sig(|a, b| b); // ought to return `a`
    |                       ^
 
-error: unsatisfied lifetime constraints
-  --> $DIR/return-wrong-bound-region.rs:21:23
-   |
-LL |     expect_sig(|a, b| b); // ought to return `a`
-   |                 -  -  ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`
-   |                 |  |
-   |                 |  has type `&'1 i32`
-   |                 has type `&'2 i32`
-
 note: No external requirements
   --> $DIR/return-wrong-bound-region.rs:21:16
    |
@@ -24,6 +15,15 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
                for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/return-wrong-bound-region.rs:21:23
+   |
+LL |     expect_sig(|a, b| b); // ought to return `a`
+   |                 -  -  ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`
+   |                 |  |
+   |                 |  has type `&'1 i32`
+   |                 has type `&'2 i32`
+
 note: No external requirements
   --> $DIR/return-wrong-bound-region.rs:20:1
    |
diff --git a/src/test/ui/nll/closure-use-spans.rs b/src/test/ui/nll/closure-use-spans.rs
new file mode 100644 (file)
index 0000000..7ab382a
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that liveness due to a closure capture gives a special note
+
+#![feature(nll)]
+
+fn use_as_borrow_capture(mut x: i32) {
+    let y = &x;
+    x = 0; //~ ERROR
+    || *y;
+}
+
+fn use_as_borrow_mut_capture(mut x: i32) {
+    let y = &mut x;
+    x = 0; //~ ERROR
+    || *y = 1;
+}
+
+fn use_as_move_capture(mut x: i32) {
+    let y = &x;
+    x = 0; //~ ERROR
+    move || *y;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-use-spans.stderr b/src/test/ui/nll/closure-use-spans.stderr
new file mode 100644 (file)
index 0000000..7e5f962
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-use-spans.rs:17:5
+   |
+LL |     let y = &x;
+   |             -- borrow of `x` occurs here
+LL |     x = 0; //~ ERROR
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     || *y;
+   |         - borrow later captured here by closure
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-use-spans.rs:23:5
+   |
+LL |     let y = &mut x;
+   |             ------ borrow of `x` occurs here
+LL |     x = 0; //~ ERROR
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     || *y = 1;
+   |         - borrow later captured here by closure
+
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/closure-use-spans.rs:29:5
+   |
+LL |     let y = &x;
+   |             -- borrow of `x` occurs here
+LL |     x = 0; //~ ERROR
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL |     move || *y;
+   |              - borrow later captured here by closure
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/closures-in-loops.rs b/src/test/ui/nll/closures-in-loops.rs
new file mode 100644 (file)
index 0000000..c6113f3
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test messages where a closure capture conflicts with itself because it's in
+// a loop.
+
+#![feature(nll)]
+
+fn repreated_move(x: String) {
+    for i in 0..10 {
+        || x; //~ ERROR
+    }
+}
+
+fn repreated_mut_borrow(mut x: String) {
+    let mut v = Vec::new();
+    for i in 0..10 {
+        v.push(|| x = String::new()); //~ ERROR
+    }
+}
+
+fn repreated_unique_borrow(x: &mut String) {
+    let mut v = Vec::new();
+    for i in 0..10 {
+        v.push(|| *x = String::new()); //~ ERROR
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr
new file mode 100644 (file)
index 0000000..9758a80
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/closures-in-loops.rs:18:9
+   |
+LL |         || x; //~ ERROR
+   |         ^^ - use occurs due to use in closure
+   |         |
+   |         value moved into closure here in previous iteration of loop
+   |
+   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/closures-in-loops.rs:25:16
+   |
+LL |         v.push(|| x = String::new()); //~ ERROR
+   |                ^^ - borrows occur due to use of `x` in closure
+   |                |
+   |                mutable borrow starts here in previous iteration of loop
+
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/closures-in-loops.rs:32:16
+   |
+LL |         v.push(|| *x = String::new()); //~ ERROR
+   |                ^^  - borrows occur due to use of `x` in closure
+   |                |
+   |                closures are constructed here in different iterations of loop
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0382, E0499, E0524.
+For more information about an error, try `rustc --explain E0382`.
index ce07e2b0e2184aeed096b59ed3735d3082cc190a..472ac2cf1e84c2415236a4b2f348416b3be84d60 100644 (file)
@@ -55,10 +55,19 @@ fn parse_dot_or_call_expr_with(mut attrs: Vec<u32>) {
     );
 }
 
+// Found when trying to bootstrap rustc
+fn if_guard(x: Result<i32, i32>) {
+    match x {
+        Ok(mut r) | Err(mut r) if true => r = 1,
+        _ => (),
+    }
+}
+
 fn main() {
     ref_argument(0);
     mutable_upvar();
     generator_mutable_upvar();
     ref_closure_argument();
     parse_dot_or_call_expr_with(Vec::new());
+    if_guard(Ok(0));
 }
index b955a51e38d73433184f516491839ff030d7074c..580dce3c0fe632691f65bc1d8d35d1e153275397 100644 (file)
@@ -63,9 +63,18 @@ LL |         match map.get() {
 LL |             Some(v) => {
 LL |                 map.set(String::new()); // Both AST and MIR error here
    |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
-...
-LL |                 return v;
-   |                        - borrow later used here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
+  --> $DIR/get_default.rs:41:1
+   |
+LL | / fn err(map: &mut Map) -> &String {
+LL | |     loop {
+LL | |         match map.get() {
+LL | |             Some(v) => {
+...  |
+LL | |     }
+LL | | }
+   | |_^
 
 error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
   --> $DIR/get_default.rs:51:17
index 75194bf55bc9f1a3b9864d3648790578ea782852..2f8eab907c7bb5185353420d28460e9ac2cd38e6 100644 (file)
@@ -63,9 +63,18 @@ LL |         match map.get() {
 LL |             Some(v) => {
 LL |                 map.set(String::new()); // Both AST and MIR error here
    |                 ^^^ mutable borrow occurs here
-...
-LL |                 return v;
-   |                        - borrow later used here
+   |
+note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
+  --> $DIR/get_default.rs:41:1
+   |
+LL | / fn err(map: &mut Map) -> &String {
+LL | |     loop {
+LL | |         match map.get() {
+LL | |             Some(v) => {
+...  |
+LL | |     }
+LL | | }
+   | |_^
 
 error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
   --> $DIR/get_default.rs:51:17
index 269bc368305cbaba34330022865d3049eb966bcd..2ecfe03e7de6250e2e60b50a1360f20ce5bf1b3e 100644 (file)
@@ -8,7 +8,7 @@ LL |            self.thing.bar(|| {
    | ||
 LL | ||         //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502]
 LL | ||             &self.number;
-   | ||              ---- previous borrow occurs due to use of `self` in closure
+   | ||              ---- first borrow occurs due to use of `self` in closure
 LL | ||         });
    | ||          ^
    | ||__________|
diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs
new file mode 100644 (file)
index 0000000..1c509c5
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+
+#![allow(warnings)]
+#![feature(nll)]
+
+trait Bazinga { }
+impl<F> Bazinga for F { }
+
+fn produce1<'a>(data: &'a u32) -> impl Bazinga + 'a {
+    let x = move || {
+        let _data: &'a u32 = data;
+    };
+    x
+}
+
+fn produce2<'a>(data: &'a mut Vec<&'a u32>, value: &'a u32) -> impl Bazinga + 'a {
+    let x = move || {
+        let value: &'a u32 = value;
+        data.push(value);
+    };
+    x
+}
+
+
+fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazinga + 'a {
+    let x = move || {
+        let value: &'a u32 = value;
+        data.push(value);
+    };
+    x
+}
+
+fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
+    let x = move || { //~ ERROR lifetime mismatch
+        let value: &'a u32 = value;
+        data.push(value);
+    };
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr
new file mode 100644 (file)
index 0000000..4a7c10c
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/issue-52113.rs:43:9
+   |
+LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
+   |                                  --------------------         ------- these two types are declared with different lifetimes...
+LL |     let x = move || { //~ ERROR lifetime mismatch
+   |         ^ ...but data from `value` flows into `data` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/nll/issue-52133.rs b/src/test/ui/nll/issue-52133.rs
deleted file mode 100644 (file)
index 1c509c5..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-
-#![allow(warnings)]
-#![feature(nll)]
-
-trait Bazinga { }
-impl<F> Bazinga for F { }
-
-fn produce1<'a>(data: &'a u32) -> impl Bazinga + 'a {
-    let x = move || {
-        let _data: &'a u32 = data;
-    };
-    x
-}
-
-fn produce2<'a>(data: &'a mut Vec<&'a u32>, value: &'a u32) -> impl Bazinga + 'a {
-    let x = move || {
-        let value: &'a u32 = value;
-        data.push(value);
-    };
-    x
-}
-
-
-fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazinga + 'a {
-    let x = move || {
-        let value: &'a u32 = value;
-        data.push(value);
-    };
-    x
-}
-
-fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
-    let x = move || { //~ ERROR lifetime mismatch
-        let value: &'a u32 = value;
-        data.push(value);
-    };
-    x
-}
-
-fn main() { }
diff --git a/src/test/ui/nll/issue-52133.stderr b/src/test/ui/nll/issue-52133.stderr
deleted file mode 100644 (file)
index c184100..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/issue-52133.rs:43:9
-   |
-LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
-   |                                  --------------------         ------- these two types are declared with different lifetimes...
-LL |     let x = move || { //~ ERROR lifetime mismatch
-   |         ^ ...but data from `value` flows into `data` here
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0623`.
index fc2a3c43f7589df2edd7aa3deea5207c7ed91e7c..cdc407985fe63681ff63dc5be93a97a7772b654c 100644 (file)
@@ -7,6 +7,10 @@ LL |     g
 error: unsatisfied lifetime constraints
   --> $DIR/mir_check_cast_closure.rs:16:28
    |
+LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
+   |        --  -- lifetime `'b` defined here
+   |        |
+   |        lifetime `'a` defined here
 LL |     let g: fn(_, _) -> _ = |_x, y| y;
    |                            ^^^^^^^^^ cast requires that `'b` must outlive `'a`
 
index 7bd0595f3b5ccdd3f7b47e82882348acba14ff9e..02ecd05e5f931baf5892a7779ef9ba383384147b 100644 (file)
@@ -8,7 +8,9 @@ error: unsatisfied lifetime constraints
   --> $DIR/mir_check_cast_unsize.rs:17:46
    |
 LL |   fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
-   |  ______________________________________________^
+   |  ________--____________________________________^
+   | |        |
+   | |        lifetime `'a` defined here
 LL | |     //~^ ERROR unsatisfied lifetime constraints
 LL | |     x
 LL | |     //~^ WARNING not reporting region error due to nll
index 3f2c651ae3a6af343245fc10d536e088545fcd6a..53d60d3f6d649a4b4ec0b3d9efbc1dc8c14f4ba7 100644 (file)
@@ -59,6 +59,7 @@ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
 LL |     let C(D(s)) = c;
    |             -     ^ cannot move out of here
    |             |
+   |             data moved here
    |             help: to prevent move, use ref or ref mut: `ref s`
 
 error[E0507]: cannot move out of borrowed content
@@ -88,7 +89,10 @@ LL |     match x {
    |           ^ cannot move out of here
 ...
 LL |         B::U(D(s)) => (),
-   |                - help: to prevent move, use ref or ref mut: `ref s`
+   |                -
+   |                |
+   |                data moved here
+   |                help: to prevent move, use ref or ref mut: `ref s`
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:105:11
@@ -97,7 +101,10 @@ LL |     match x {
    |           ^ cannot move out of here
 ...
 LL |         (D(s), &t) => (),
-   |            - help: to prevent move, use ref or ref mut: `ref s`
+   |            -
+   |            |
+   |            data moved here
+   |            help: to prevent move, use ref or ref mut: `ref s`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:105:11
@@ -106,21 +113,25 @@ LL |     match x {
    |           ^ cannot move out of borrowed content
 ...
 LL |         (D(s), &t) => (),
-   |                 - help: to prevent move, use ref or ref mut: `ref t`
+   |                 -
+   |                 |
+   |                 data moved here
+   |                 help: to prevent move, use ref or ref mut: `ref t`
 
 error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:115:11
    |
 LL |     match x {
    |           ^ cannot move out of here
+LL |     //~^ ERROR
+LL |         F(s, mut t) => (),
+   |           -  ----- ... and here
+   |           |
+   |           data moved here
 help: to prevent move, use ref or ref mut
    |
-LL |         F(ref s, mut t) => (),
-   |           ^^^^^
-help: to prevent move, use ref or ref mut
-   |
-LL |         F(s, ref mut t) => (),
-   |              ^^^^^^^^^
+LL |         F(ref s, ref mut t) => (),
+   |           ^^^^^  ^^^^^^^^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:123:11
diff --git a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs
new file mode 100644 (file)
index 0000000..be38556
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that mutable promoted length zero arrays don't check for conflicting
+// access
+
+// run-pass
+
+#![feature(nll)]
+
+pub fn main() {
+    let mut x: Vec<&[i32; 0]> = Vec::new();
+    for i in 0..10 {
+        x.push(&[]);
+    }
+}
index f40e38c63f5ac28634c488df2b68d67a60134e13..f441085f242edddc102c2078ba1fd1691134b523 100644 (file)
@@ -1,16 +1,13 @@
 error[E0597]: borrowed value does not live long enough
   --> $DIR/return-ref-mut-issue-46557.rs:17:21
    |
-LL |   fn gimme_static_mut() -> &'static mut u32 {
-   |  ___________________________________________-
-LL | |     let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
-   | |                     ^^^^^^^ temporary value does not live long enough
-LL | |     x
-LL | | }
-   | | -
-   | | |
-   | |_temporary value only lives until here
-   |   borrow later used here
+LL |     let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
+   |                     ^^^^^^^ temporary value does not live long enough
+LL |     x
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
 
 error: aborting due to previous error
 
index dd12e8220c456afe25e74ae2de971484a396bda9..6d2170729ffb9f9db5f8db532bfbdf92710f3819 100644 (file)
@@ -25,14 +25,6 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: number of external vids: 4
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
-error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:35:23
-   |
-LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
-
 note: No external requirements
   --> $DIR/projection-no-regions-closure.rs:31:1
    |
@@ -50,6 +42,14 @@ LL | | }
                T
            ]
 
+error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+  --> $DIR/projection-no-regions-closure.rs:35:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
+
 note: External requirements
   --> $DIR/projection-no-regions-closure.rs:45:23
    |
@@ -97,14 +97,6 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: number of external vids: 5
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
-error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:53:23
-   |
-LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
-
 note: No external requirements
   --> $DIR/projection-no-regions-closure.rs:49:1
    |
@@ -123,6 +115,14 @@ LL | | }
                T
            ]
 
+error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+  --> $DIR/projection-no-regions-closure.rs:53:23
+   |
+LL |     with_signature(x, |mut y| Box::new(y.next()))
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
+
 note: External requirements
   --> $DIR/projection-no-regions-closure.rs:64:23
    |
index 456c52d3a51b84890f26f2344a5698870e939b3c..2b0e682f85161e3c0e90be2f09a44bc8ed597869 100644 (file)
@@ -32,20 +32,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where T: '_#2r
    = note: where '_#1r: '_#2r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:55:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
-
-error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:55:5
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
 note: No external requirements
   --> $DIR/projection-one-region-closure.rs:51:1
    |
@@ -63,6 +49,25 @@ LL | | }
                T
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/projection-one-region-closure.rs:55:5
+   |
+LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                          --  -- lifetime `'b` defined here
+   |                          |
+   |                          lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:55:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
+
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:67:29
    |
@@ -80,20 +85,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where T: '_#3r
    = note: where '_#2r: '_#3r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:67:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
-
-error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:67:5
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
 note: No external requirements
   --> $DIR/projection-one-region-closure.rs:62:1
    |
@@ -112,6 +103,25 @@ LL | | }
                T
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/projection-one-region-closure.rs:67:5
+   |
+LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                           --  -- lifetime `'b` defined here
+   |                           |
+   |                           lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:67:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:89:29
    |
@@ -129,20 +139,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where T: '_#3r
    = note: where '_#2r: '_#3r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:89:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
-
-error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:89:5
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
 note: No external requirements
   --> $DIR/projection-one-region-closure.rs:74:1
    |
@@ -161,6 +157,25 @@ LL | | }
                T
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/projection-one-region-closure.rs:89:5
+   |
+LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                        --  -- lifetime `'b` defined here
+   |                        |
+   |                        lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:89:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:102:29
    |
index 35c0405ff89e23388d578fb495689d70e9596e6a..739bde4a481c57b1208252190af701dd207e8a3a 100644 (file)
@@ -31,12 +31,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: number of external vids: 5
    = note: where '_#1r: '_#2r
 
-error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:47:5
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:43:1
    |
@@ -54,6 +48,17 @@ LL | | }
                T
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:5
+   |
+LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                          --  -- lifetime `'b` defined here
+   |                          |
+   |                          lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:58:29
    |
@@ -70,12 +75,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: number of external vids: 5
    = note: where '_#2r: '_#3r
 
-error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:58:5
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:53:1
    |
@@ -94,6 +93,17 @@ LL | | }
                T
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/projection-one-region-trait-bound-closure.rs:58:5
+   |
+LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                           --  -- lifetime `'b` defined here
+   |                           |
+   |                           lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:79:29
    |
@@ -110,12 +120,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: number of external vids: 5
    = note: where '_#2r: '_#3r
 
-error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:79:5
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:64:1
    |
@@ -134,6 +138,17 @@ LL | | }
                T
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/projection-one-region-trait-bound-closure.rs:79:5
+   |
+LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                        --  -- lifetime `'b` defined here
+   |                        |
+   |                        lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:90:29
    |
index a713971d17cb3954d4be3dc8ff6f4757fd3337f9..6838e0f3b3d01505b3cc6be6855f8382825f0152 100644 (file)
@@ -38,14 +38,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: number of external vids: 6
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
-error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`...
-
 note: No external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:44:1
    |
@@ -64,6 +56,14 @@ LL | | }
                T
            ]
 
+error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`...
+
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
    |
@@ -81,14 +81,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: number of external vids: 6
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
-error[E0309]: the associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `<T as Anything<'_#7r, '_#8r>>::AssocType: ReEarlyBound(0, 'a)`...
-
 note: No external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:54:1
    |
@@ -108,6 +100,14 @@ LL | | }
                T
            ]
 
+error[E0309]: the associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
+  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Anything<'_#7r, '_#8r>>::AssocType: ReEarlyBound(0, 'a)`...
+
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
    |
@@ -125,14 +125,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: number of external vids: 6
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
-error[E0309]: the associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `<T as Anything<'_#7r, '_#8r>>::AssocType: ReEarlyBound(0, 'a)`...
-
 note: No external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:65:1
    |
@@ -152,6 +144,14 @@ LL | | }
                T
            ]
 
+error[E0309]: the associated type `<T as Anything<'_#7r, '_#8r>>::AssocType` may not live long enough
+  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
+   |
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as Anything<'_#7r, '_#8r>>::AssocType: ReEarlyBound(0, 'a)`...
+
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:91:29
    |
@@ -239,12 +239,6 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
-error: unsatisfied lifetime constraints
-  --> $DIR/projection-two-region-trait-bound-closure.rs:108:5
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
 note: No external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:104:1
    |
@@ -262,6 +256,17 @@ LL | | }
                T
            ]
 
+error: unsatisfied lifetime constraints
+  --> $DIR/projection-two-region-trait-bound-closure.rs:108:5
+   |
+LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                --  -- lifetime `'b` defined here
+   |                |
+   |                lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:119:29
    |
index 39382df8d8a91433e6fe68ecfd9b0608ac7254b4..87f55b4e14d9652caca1fdd974a41026978f9b60 100644 (file)
@@ -60,14 +60,6 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: number of external vids: 4
    = note: where T: '_#1r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
-   |
-LL |     twice(cell, value, |a, b| invoke(a, b));
-   |                        ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`...
-
 note: No external requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:41:1
    |
@@ -83,6 +75,14 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
+   |
+LL |     twice(cell, value, |a, b| invoke(a, b));
+   |                        ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`...
+
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0309`.
index 8babbe3fd97d2a6f0cb9f96272c9eca2120a909d..aec0d98c79aa47671f49d165350dbeb87d2838fe 100644 (file)
@@ -25,14 +25,6 @@ LL |     with_signature(x, |y| y)
    = note: number of external vids: 4
    = note: where T: '_#2r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23
-   |
-LL |     with_signature(x, |y| y)
-   |                       ^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
-
 note: No external requirements
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:25:1
    |
@@ -50,6 +42,14 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23
+   |
+LL |     with_signature(x, |y| y)
+   |                       ^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5
    |
index b9426eba0f66d273e9383c616f33efffd36dd99c..67a158860d64c1d7ffcf6705472c5bb65499c852 100644 (file)
@@ -31,21 +31,6 @@ LL | |     })
    = note: number of external vids: 4
    = note: where T: '_#1r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26
-   |
-LL |       with_signature(a, b, |x, y| {
-   |  __________________________^
-LL | |         //~^ ERROR the parameter type `T` may not live long enough
-LL | |         //
-LL | |         // See `correct_region`, which explains the point of this
-...  |
-LL | |         //~^ WARNING not reporting region error due to nll
-LL | |     })
-   | |_____^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`...
-
 note: No external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:36:1
    |
@@ -62,6 +47,21 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |         //~^ ERROR the parameter type `T` may not live long enough
+LL | |         //
+LL | |         // See `correct_region`, which explains the point of this
+...  |
+LL | |         //~^ WARNING not reporting region error due to nll
+LL | |     })
+   | |_____^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`...
+
 note: External requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:54:26
    |
@@ -122,20 +122,6 @@ LL | |     })
    = note: number of external vids: 5
    = note: where T: '_#2r
 
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
-   |
-LL |       with_signature(a, b, |x, y| {
-   |  __________________________^
-LL | |         //~^ ERROR the parameter type `T` may not live long enough
-LL | |         // See `correct_region`
-LL | |         require(&x, &y)
-LL | |         //~^ WARNING not reporting region error due to nll
-LL | |     })
-   | |_____^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`...
-
 note: No external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1
    |
@@ -153,6 +139,20 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
+   |
+LL |       with_signature(a, b, |x, y| {
+   |  __________________________^
+LL | |         //~^ ERROR the parameter type `T` may not live long enough
+LL | |         // See `correct_region`
+LL | |         require(&x, &y)
+LL | |         //~^ WARNING not reporting region error due to nll
+LL | |     })
+   | |_____^
+   |
+   = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`...
+
 note: External requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:89:26
    |
index ae7193ef4fa793d44b6a515ff55774f76277ab51..d0d6bd4c78570c08bd349033b32a4855d9f205e6 100644 (file)
@@ -1,44 +1,54 @@
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:19:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:19:34
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------        ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |      - `x` dropped here while still borrowed
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:19:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:19:45
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------                   ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |      - `y` dropped here while still borrowed
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:34:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:34:34
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------        ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |      - `x` dropped here while still borrowed
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:34:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:34:45
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------                   ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |      - `y` dropped here while still borrowed
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:65:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:65:34
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------        ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |     - `x` dropped here while still borrowed
@@ -50,10 +60,12 @@ LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |          ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:65:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:65:45
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------                   ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |     - `y` dropped here while still borrowed
@@ -65,10 +77,12 @@ LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |          ^^
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:76:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:76:34
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------        ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |     - `x` dropped here while still borrowed
@@ -80,10 +94,12 @@ LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |          ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:76:17
+  --> $DIR/region-borrow-params-issue-29793-small.rs:76:45
    |
 LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                 ---------                   ^ borrowed value does not live long enough
+   |                 |
+   |                 value captured here
 ...
 LL |     };
    |     - `y` dropped here while still borrowed
@@ -95,10 +111,12 @@ LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |          ^^
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:100:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:100:38
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------        ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `x` dropped here while still borrowed
@@ -110,10 +128,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:100:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:100:49
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------                   ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `y` dropped here while still borrowed
@@ -125,10 +145,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:114:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:114:38
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------        ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `x` dropped here while still borrowed
@@ -140,10 +162,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:114:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:114:49
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------                   ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `y` dropped here while still borrowed
@@ -155,10 +179,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:142:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:142:38
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------        ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `x` dropped here while still borrowed
@@ -170,10 +196,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:142:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:142:49
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------                   ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `y` dropped here while still borrowed
@@ -185,10 +213,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:157:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:157:38
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------        ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `x` dropped here while still borrowed
@@ -200,10 +230,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:157:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:157:49
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------                   ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `y` dropped here while still borrowed
@@ -215,10 +247,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:185:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:185:38
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------        ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `x` dropped here while still borrowed
@@ -230,10 +264,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:185:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:185:49
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------                   ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `y` dropped here while still borrowed
@@ -245,10 +281,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `x` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:199:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:199:38
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------        ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `x` dropped here while still borrowed
@@ -260,10 +298,12 @@ LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
    |              ^^
 
 error[E0597]: `y` does not live long enough
-  --> $DIR/region-borrow-params-issue-29793-small.rs:199:21
+  --> $DIR/region-borrow-params-issue-29793-small.rs:199:49
    |
 LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                     ---------                   ^ borrowed value does not live long enough
+   |                     |
+   |                     value captured here
 ...
 LL |         }
    |         - `y` dropped here while still borrowed
index 13e34d85210a785d33d277ec3a68d38aa0df5887..1b5bb7d5007798038855dcb2287971fb8a05df2b 100644 (file)
@@ -1,13 +1,14 @@
 error[E0597]: `y` does not live long enough
-  --> $DIR/regions-nested-fns-2.rs:16:9
+  --> $DIR/regions-nested-fns-2.rs:18:25
    |
-LL | /         |z| {
-LL | |             //~^ ERROR E0373
-LL | |             if false { &y } else { z }
-LL | |         });
-   | |_________^ borrowed value does not live long enough
-LL |   }
-   |   - `y` dropped here while still borrowed
+LL |         |z| {
+   |         --- value captured here
+LL |             //~^ ERROR E0373
+LL |             if false { &y } else { z }
+   |                         ^ borrowed value does not live long enough
+LL |         });
+LL | }
+   | - `y` dropped here while still borrowed
    |
    = note: borrowed value must be valid for the static lifetime...
 
index 10384e3b7ca291be7c565c19f3c138764854fd1d..606d678542269afda8d2b76830655b676543c122 100644 (file)
@@ -7,7 +7,7 @@ LL |         foo.mutate();
    |         ^^^^^^^^^^^^ mutable borrow occurs here
 LL |         //~^ ERROR cannot borrow `foo` as mutable
 LL |         println!("foo={:?}", *string);
-   |                              ------- borrow later used here
+   |                              ------- borrow used here in later iteration of loop
 
 error: aborting due to previous error
 
index f7a6b560280800892b5c2c58766f6e03539b1011..f50419434ae1ddfa518d5ef64f49bad26d7ad865 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:macro-use-warned-against2.rs
 // compile-pass
 
-#![warn(rust_2018_idioms, unused)]
+#![warn(macro_use_extern_crate, unused)]
 #![feature(use_extern_macros)]
 
 #[macro_use] //~ WARN should be replaced at use sites with a `use` statement
index bebad31510f566e5849104bef3e73fc84cc9e092..7af404fab790e432ac20cee4d7e1637fe92a9124 100644 (file)
@@ -7,9 +7,8 @@ LL | #[macro_use] //~ WARN should be replaced at use sites with a `use` statemen
 note: lint level defined here
   --> $DIR/macro-use-warned-against.rs:15:9
    |
-LL | #![warn(rust_2018_idioms, unused)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: #[warn(macro_use_extern_crate)] implied by #[warn(rust_2018_idioms)]
+LL | #![warn(macro_use_extern_crate, unused)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused `#[macro_use]` import
   --> $DIR/macro-use-warned-against.rs:20:1
@@ -18,9 +17,9 @@ LL | #[macro_use] //~ WARN unused `#[macro_use]`
    | ^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/macro-use-warned-against.rs:15:27
+  --> $DIR/macro-use-warned-against.rs:15:33
    |
-LL | #![warn(rust_2018_idioms, unused)]
-   |                           ^^^^^^
+LL | #![warn(macro_use_extern_crate, unused)]
+   |                                 ^^^^^^
    = note: #[warn(unused_imports)] implied by #[warn(unused)]
 
index 366bfc8fa20a5a013bc9c293f1a52c855836d143..4a693a3b05d4ea1f38770055e1a9857d8b71b25f 100644 (file)
@@ -26,7 +26,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
    |
 LL | fn assign_field2<'a>(x: &'a Own<Point>) {
-   |                         -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
+   |                         -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>`
 LL |     x.y = 3; //~ ERROR cannot borrow
    |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -58,7 +58,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
    |
 LL | fn assign_method2<'a>(x: &'a Own<Point>) {
-   |                          -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
+   |                          -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>`
 LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
    |      ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
index 69bf246ff3fef61d645f38bb58a528901b3c9f45..44a5062cb4d430f13ab1299268f80c8b6a5bc4f0 100644 (file)
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
    |
 LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
-   |                             -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
+   |                             -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>`
 LL |     &mut **x //~ ERROR cannot borrow
    |           ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -26,7 +26,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
    |
 LL | fn assign2<'a>(x: &'a Own<isize>) {
-   |                   -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
+   |                   -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>`
 LL |     **x = 3; //~ ERROR cannot borrow
    |      ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
index b3563f1b6203cfa0ef91b900b6f4ef3a261abcc7..c7dbc043cdaee3fa78e23f7525645f50516e5a44 100644 (file)
@@ -8,7 +8,7 @@ LL |       f(Box::new(|| {
    | |
 LL | |     //~^ ERROR: cannot borrow `f` as mutable more than once
 LL | |         f((Box::new(|| {})))
-   | |         - borrow occurs due to use of `f` in closure
+   | |         - second borrow occurs due to use of `f` in closure
 LL | |     }));
    | |_______- borrow later used here
 
@@ -37,18 +37,17 @@ LL |         foo(f);
 error[E0505]: cannot move out of `f` because it is borrowed
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:65:16
    |
-LL |        f(Box::new(|a| {
-   |   _____-__________^
-   |  |     |
-   |  |_____borrow of `f` occurs here
-   | ||
-LL | ||         foo(f);
-LL | ||         //~^ ERROR cannot move `f` into closure because it is borrowed
-LL | ||         //~| ERROR cannot move out of captured outer variable in an `FnMut` closure
-LL | ||     }), 3);
-   | ||_____^____- borrow later used here
-   |  |_____|
-   |        move out of `f` occurs here
+LL |       f(Box::new(|a| {
+   |       -          ^^^ move out of `f` occurs here
+   |       |
+   |  _____borrow of `f` occurs here
+   | |
+LL | |         foo(f);
+   | |             - move occurs due to use in closure
+LL | |         //~^ ERROR cannot move `f` into closure because it is borrowed
+LL | |         //~| ERROR cannot move out of captured outer variable in an `FnMut` closure
+LL | |     }), 3);
+   | |__________- borrow later used here
 
 error: aborting due to 5 previous errors
 
index 225ed0f9cc832c50b66076604ea79f2190e3a316..08e4b9ec9faa2b055b1dacda481ac3232639ea48 100644 (file)
@@ -9,8 +9,6 @@ LL | }
    | |
    | `*m` dropped here while still borrowed
    | borrow later used here, when `m` is dropped
-   |
-   = note: values in a scope are dropped in the opposite order they are defined
 
 error: aborting due to previous error
 
index 6c0373ce1570a176a2001345ce741e4f128d2a59..76a25fa661ece728276f263d55f84559589eeba4 100644 (file)
@@ -1,25 +1,25 @@
-error[E0597]: `b3` does not live long enough
-  --> $DIR/dropck_arr_cycle_checked.rs:105:24
+error[E0597]: `b2` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:103:24
    |
-LL |     b1.a[1].v.set(Some(&b3));
+LL |     b1.a[0].v.set(Some(&b2));
    |                        ^^^ borrowed value does not live long enough
 ...
 LL | }
    | -
    | |
-   | `b3` dropped here while still borrowed
+   | `b2` dropped here while still borrowed
    | borrow later used here, when `b1` is dropped
 
-error[E0597]: `b2` does not live long enough
-  --> $DIR/dropck_arr_cycle_checked.rs:103:24
+error[E0597]: `b3` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:105:24
    |
-LL |     b1.a[0].v.set(Some(&b2));
+LL |     b1.a[1].v.set(Some(&b3));
    |                        ^^^ borrowed value does not live long enough
 ...
 LL | }
    | -
    | |
-   | `b2` dropped here while still borrowed
+   | `b3` dropped here while still borrowed
    | borrow later used here, when `b1` is dropped
 
 error[E0597]: `b1` does not live long enough
index c0950e79296784067ecc8d666f505e5c85aa7da6..e6f43e0a71b56f5f34ac8db460714b4255a2e951 100644 (file)
@@ -1,25 +1,25 @@
-error[E0597]: `c3` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:115:24
+error[E0597]: `c2` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:113:24
    |
-LL |     c1.v[1].v.set(Some(&c3));
+LL |     c1.v[0].v.set(Some(&c2));
    |                        ^^^ borrowed value does not live long enough
 ...
 LL | }
    | -
    | |
-   | `c3` dropped here while still borrowed
+   | `c2` dropped here while still borrowed
    | borrow later used here, when `c1` is dropped
 
-error[E0597]: `c2` does not live long enough
-  --> $DIR/dropck_vec_cycle_checked.rs:113:24
+error[E0597]: `c3` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:115:24
    |
-LL |     c1.v[0].v.set(Some(&c2));
+LL |     c1.v[1].v.set(Some(&c3));
    |                        ^^^ borrowed value does not live long enough
 ...
 LL | }
    | -
    | |
-   | `c2` dropped here while still borrowed
+   | `c3` dropped here while still borrowed
    | borrow later used here, when `c1` is dropped
 
 error[E0597]: `c1` does not live long enough
index f264ea1f916769b274b99efbed7166297284daf0..f42cf6500e2ead35b20b5605e5576c8f670f9106 100644 (file)
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
   --> $DIR/mut-arg-hint.rs:18:5
    |
 LL | pub fn foo<'a>(mut a: &'a String) {
-   |                       ---------- help: consider changing this to be a mutable reference: `&mut std::string::String`
+   |                       ---------- help: consider changing this to be a mutable reference: `&'a mut String`
 LL |     a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
    |     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
index 049618fe4744bbc618dc5329dd26dbd4b5581c12..2a82e1b8ada8c9c26ae4d70599258c83534149a0 100644 (file)
@@ -1,21 +1,21 @@
-error[E0597]: `b` does not live long enough
-  --> $DIR/range-2.rs:17:13
+error[E0597]: `a` does not live long enough
+  --> $DIR/range-2.rs:17:9
    |
 LL |         &a..&b
-   |             ^^ borrowed value does not live long enough
+   |         ^^ borrowed value does not live long enough
 LL |     };
-   |     - `b` dropped here while still borrowed
+   |     - `a` dropped here while still borrowed
 ...
 LL |     r.use_ref();
    |     - borrow later used here
 
-error[E0597]: `a` does not live long enough
-  --> $DIR/range-2.rs:17:9
+error[E0597]: `b` does not live long enough
+  --> $DIR/range-2.rs:17:13
    |
 LL |         &a..&b
-   |         ^^ borrowed value does not live long enough
+   |             ^^ borrowed value does not live long enough
 LL |     };
-   |     - `a` dropped here while still borrowed
+   |     - `b` dropped here while still borrowed
 ...
 LL |     r.use_ref();
    |     - borrow later used here
index 08ca100c247dc16d2b083ea0f7e54ddfb1063f7c..7aaec700d8985559080944c057955878e4223f7f 100644 (file)
@@ -2,7 +2,7 @@ error[E0597]: `x` does not live long enough
   --> $DIR/regions-escape-loop-via-variable.rs:21:13
    |
 LL |         let x = 1 + *p;
-   |                     -- borrow later used here
+   |                     -- borrow used here in later iteration of loop
 LL |         p = &x;
    |             ^^ borrowed value does not live long enough
 LL |     }
index 33fca7fa703b0589fc5282e55f98c116d00eefe3..2dc758428ef3a48de7de92f51460fecec267afc9 100644 (file)
@@ -7,7 +7,7 @@ LL |     while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
    |           ^ use of borrowed `x`
 LL |         let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
 LL |         _y.push(&mut z);
-   |         -- borrow later used here
+   |         -- borrow used here in later iteration of loop
 
 error[E0503]: cannot use `x` because it was mutably borrowed
   --> $DIR/regions-escape-loop-via-vec.rs:16:21
@@ -18,7 +18,18 @@ LL |     while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
 LL |         let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
    |                     ^ use of borrowed `x`
 LL |         _y.push(&mut z);
-   |         -- borrow later used here
+   |         -- borrow used here in later iteration of loop
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/regions-escape-loop-via-vec.rs:17:17
+   |
+LL |         _y.push(&mut z);
+   |         --      ^^^^^^ borrowed value does not live long enough
+   |         |
+   |         borrow used here in later iteration of loop
+...
+LL |     }
+   |     - `z` dropped here while still borrowed
 
 error[E0503]: cannot use `x` because it was mutably borrowed
   --> $DIR/regions-escape-loop-via-vec.rs:19:9
@@ -27,22 +38,11 @@ LL |     let mut _y = vec![&mut x];
    |                       ------ borrow of `x` occurs here
 ...
 LL |         _y.push(&mut z);
-   |         -- borrow later used here
+   |         -- borrow used here in later iteration of loop
 LL |         //~^ ERROR `z` does not live long enough
 LL |         x += 1; //~ ERROR cannot assign
    |         ^^^^^^ use of borrowed `x`
 
-error[E0597]: `z` does not live long enough
-  --> $DIR/regions-escape-loop-via-vec.rs:17:17
-   |
-LL |         _y.push(&mut z);
-   |         --      ^^^^^^ borrowed value does not live long enough
-   |         |
-   |         borrow later used here
-...
-LL |     }
-   |     - `z` dropped here while still borrowed
-
 error: aborting due to 4 previous errors
 
 Some errors occurred: E0503, E0597.
index 7f7217b8004a6338709027816597c38c07d48d31..c14cb7098933f1bb782ab318850ee7de21f81918 100644 (file)
@@ -1,18 +1,3 @@
-error[E0597]: `y` does not live long enough
-  --> $DIR/send-is-not-static-ensures-scoping.rs:29:16
-   |
-LL |           scoped(|| {
-   |  ________________^
-LL | |             let _z = y;
-LL | |             //~^ ERROR `y` does not live long enough
-LL | |         })
-   | |_________^ borrowed value does not live long enough
-LL |       };
-   |       - `y` dropped here while still borrowed
-LL | 
-LL |       bad.join();
-   |       --- borrow later used here
-
 error[E0597]: `x` does not live long enough
   --> $DIR/send-is-not-static-ensures-scoping.rs:26:17
    |
@@ -25,6 +10,20 @@ LL |
 LL |     bad.join();
    |     --- borrow later used here
 
+error[E0597]: `y` does not live long enough
+  --> $DIR/send-is-not-static-ensures-scoping.rs:30:22
+   |
+LL |         scoped(|| {
+   |                -- value captured here
+LL |             let _z = y;
+   |                      ^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `y` dropped here while still borrowed
+LL | 
+LL |     bad.join();
+   |     --- borrow later used here
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0597`.
index 73256b4fb17c9e6ec66d32c02cf59f1e5ba2d742..60905367063a48d47c82cd3fa96862618ace5e55 100644 (file)
@@ -1,27 +1,27 @@
-error[E0597]: `y` does not live long enough
-  --> $DIR/vec_refs_data_with_early_death.rs:29:12
+error[E0597]: `x` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:27:12
    |
-LL |     v.push(&y);
+LL |     v.push(&x);
    |            ^^ borrowed value does not live long enough
 ...
 LL | }
    | -
    | |
-   | `y` dropped here while still borrowed
+   | `x` dropped here while still borrowed
    | borrow later used here, when `v` is dropped
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
-error[E0597]: `x` does not live long enough
-  --> $DIR/vec_refs_data_with_early_death.rs:27:12
+error[E0597]: `y` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:29:12
    |
-LL |     v.push(&x);
+LL |     v.push(&y);
    |            ^^ borrowed value does not live long enough
 ...
 LL | }
    | -
    | |
-   | `x` dropped here while still borrowed
+   | `y` dropped here while still borrowed
    | borrow later used here, when `v` is dropped
    |
    = note: values in a scope are dropped in the opposite order they are defined
index 69208f151360b2e45ccaef5c467ed40771c93c92..c2dc927c4b52461eb9e13af807b00bb5f2ed036d 100644 (file)
@@ -12,6 +12,8 @@
 // ignore-aarch64
 // ignore-wasm
 // ignore-emscripten
+// ignore-mips
+// ignore-mips64
 // gate-test-sse4a_target_feature
 // gate-test-powerpc_target_feature
 // gate-test-avx512_target_feature
index a6f794a1a1ab2660fbefe671baf1224a7869eaac..24141d0064fb0f2c0cf92dd52a710ad22bb54785 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
-  --> $DIR/target-feature-gate.rs:26:18
+  --> $DIR/target-feature-gate.rs:28:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
index 8983c0ea79bd944bf239442e2460b04d8e6c154a..fe611141379c49f746cd368bc4a6af9389c51d1b 100644 (file)
@@ -13,6 +13,7 @@
 // ignore-wasm
 // ignore-emscripten
 // ignore-mips
+// ignore-mips64
 // ignore-powerpc
 // ignore-powerpc64
 // ignore-powerpc64le
index d4e1c978104b635ebd15a3d7ab5eb988a2537e7a..21c73b7ddbff0ed31faf0a6cdf786abed298332c 100644 (file)
@@ -1,35 +1,35 @@
 error: #[target_feature] attribute must be of the form #[target_feature(..)]
-  --> $DIR/target-feature-wrong.rs:25:1
+  --> $DIR/target-feature-wrong.rs:26:1
    |
 LL | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/target-feature-wrong.rs:27:18
+  --> $DIR/target-feature-wrong.rs:28:18
    |
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:29:18
+  --> $DIR/target-feature-wrong.rs:30:18
    |
 LL | #[target_feature(bar)]
    |                  ^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:31:18
+  --> $DIR/target-feature-wrong.rs:32:18
    |
 LL | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] can only be applied to `unsafe` function
-  --> $DIR/target-feature-wrong.rs:35:1
+  --> $DIR/target-feature-wrong.rs:36:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: attribute should be applied to a function
-  --> $DIR/target-feature-wrong.rs:39:1
+  --> $DIR/target-feature-wrong.rs:40:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL | mod another {}
    | -------------- not a function
 
 error: cannot use #[inline(always)] with #[target_feature]
-  --> $DIR/target-feature-wrong.rs:43:1
+  --> $DIR/target-feature-wrong.rs:44:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/tool-attributes-disabled-1.rs b/src/test/ui/tool-attributes-disabled-1.rs
new file mode 100644 (file)
index 0000000..87d47b7
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// If macro modularization (`use_extern_macros`) is not enabled,
+// then tool attributes are treated as custom attributes.
+
+#[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler
+fn main() {}
diff --git a/src/test/ui/tool-attributes-disabled-1.stderr b/src/test/ui/tool-attributes-disabled-1.stderr
new file mode 100644 (file)
index 0000000..6302c06
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: The attribute `rustfmt::bar` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/tool-attributes-disabled-1.rs:14:1
+   |
+LL | #[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/tool-attributes-disabled-2.rs b/src/test/ui/tool-attributes-disabled-2.rs
new file mode 100644 (file)
index 0000000..160dda0
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// If macro modularization (`use_extern_macros`) is not enabled,
+// then tool attributes are treated as custom attributes.
+
+// compile-pass
+
+#![feature(custom_attribute)]
+
+#[rustfmt::bar]
+fn main() {}
diff --git a/src/test/ui/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes-misplaced-1.rs
new file mode 100644 (file)
index 0000000..b335535
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(tool_attributes)]
+
+type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
+type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
+
+#[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
+struct S;
+
+#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
+fn check() {}
+
+#[rustfmt::skip] // OK
+fn main() {
+    rustfmt; //~ ERROR expected value, found tool module `rustfmt`
+    rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+
+    rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
+}
diff --git a/src/test/ui/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes-misplaced-1.stderr
new file mode 100644 (file)
index 0000000..b9e6112
--- /dev/null
@@ -0,0 +1,46 @@
+error: cannot find derive macro `rustfmt` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:16:10
+   |
+LL | #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
+   |          ^^^^^^^
+
+error: cannot find attribute macro `rustfmt` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:19:3
+   |
+LL | #[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
+   |   ^^^^^^^
+
+error: cannot find macro `rustfmt!` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:25:5
+   |
+LL |     rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+   |     ^^^^^^^
+
+error[E0573]: expected type, found tool module `rustfmt`
+  --> $DIR/tool-attributes-misplaced-1.rs:13:10
+   |
+LL | type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
+   |          ^^^^^^^ not a type
+
+error[E0573]: expected type, found non-macro attribute `rustfmt::skip`
+  --> $DIR/tool-attributes-misplaced-1.rs:14:10
+   |
+LL | type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
+   |          ^^^^^^^^^^^^^ not a type
+
+error[E0423]: expected value, found tool module `rustfmt`
+  --> $DIR/tool-attributes-misplaced-1.rs:24:5
+   |
+LL |     rustfmt; //~ ERROR expected value, found tool module `rustfmt`
+   |     ^^^^^^^ not a value
+
+error[E0423]: expected value, found non-macro attribute `rustfmt::skip`
+  --> $DIR/tool-attributes-misplaced-1.rs:27:5
+   |
+LL |     rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
+   |     ^^^^^^^^^^^^^ not a value
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0423, E0573.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/tool-attributes-misplaced-2.rs b/src/test/ui/tool-attributes-misplaced-2.rs
new file mode 100644 (file)
index 0000000..3bb0e3d
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(tool_attributes)]
+
+#[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
+struct S;
+
+fn main() {
+    rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
+}
diff --git a/src/test/ui/tool-attributes-misplaced-2.stderr b/src/test/ui/tool-attributes-misplaced-2.stderr
new file mode 100644 (file)
index 0000000..6645226
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected a macro, found non-macro attribute
+  --> $DIR/tool-attributes-misplaced-2.rs:13:10
+   |
+LL | #[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
+   |          ^^^^^^^^^^^^^
+
+error: expected a macro, found non-macro attribute
+  --> $DIR/tool-attributes-misplaced-2.rs:17:5
+   |
+LL |     rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/tool-attributes-shadowing.rs b/src/test/ui/tool-attributes-shadowing.rs
new file mode 100644 (file)
index 0000000..7913c9f
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(tool_attributes, proc_macro_path_invoc)]
+
+mod rustfmt {}
+
+#[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
+fn main() {}
diff --git a/src/test/ui/tool-attributes-shadowing.stderr b/src/test/ui/tool-attributes-shadowing.stderr
new file mode 100644 (file)
index 0000000..f668d67
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve. Could not find `skip` in `rustfmt`
+  --> $DIR/tool-attributes-shadowing.rs:15:12
+   |
+LL | #[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
+   |            ^^^^ Could not find `skip` in `rustfmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
index 215faf6c73c369ab1e2c90f96d9867968c144335..56897baeb4eff8db1f3c8172531cb8a0f01510a7 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
   --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5
    |
 LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
-   |                        --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
+   |                        --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32`
 LL |     *t //~ ERROR
    |     ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
   --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6
    |
 LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
-   |                             --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
+   |                             --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32`
 LL |     {*t} //~ ERROR
    |      ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
index 83b2895e1d65d6ea866a090cca3202dbf9d7d8fc..fd8fb54503a6ff85fde21499942d040608360f02 100644 (file)
@@ -89,6 +89,7 @@
     "powerpc64-unknown-linux-gnu",
     "powerpc64le-unknown-linux-gnu",
     "powerpc64le-unknown-linux-musl",
+    "riscv32imac-unknown-none-elf",
     "s390x-unknown-linux-gnu",
     "sparc-unknown-linux-gnu",
     "sparc64-unknown-linux-gnu",
     "x86_64-sun-solaris",
     "x86_64-unknown-cloudabi",
     "x86_64-unknown-freebsd",
+    "x86_64-unknown-hermit",
     "x86_64-unknown-linux-gnu",
     "x86_64-unknown-linux-gnux32",
     "x86_64-unknown-linux-musl",
index 2cd36b4ed1aef1ae39a30783e006411d1a4218ac..b42488270ed29d73445d6c81d303b6a7476f6bb1 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2cd36b4ed1aef1ae39a30783e006411d1a4218ac
+Subproject commit b42488270ed29d73445d6c81d303b6a7476f6bb1
index afd91248eda02cf2968e4e02c77b6c10ecd3fd4f..7e5e4c1e7e80ed689a49101569dde2c19753dc8d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit afd91248eda02cf2968e4e02c77b6c10ecd3fd4f
+Subproject commit 7e5e4c1e7e80ed689a49101569dde2c19753dc8d
index d77261f49597291024685a535ab2a2dee54f896c..5f68d00eab1d4b9bb91044cdc0370166f33e666c 100644 (file)
@@ -231,6 +231,7 @@ pub struct TestProps {
     pub normalize_stderr: Vec<(String, String)>,
     pub failure_status: i32,
     pub run_rustfix: bool,
+    pub rustfix_only_machine_applicable: bool,
 }
 
 impl TestProps {
@@ -263,6 +264,7 @@ pub fn new() -> Self {
             normalize_stderr: vec![],
             failure_status: -1,
             run_rustfix: false,
+            rustfix_only_machine_applicable: false,
         }
     }
 
@@ -397,6 +399,11 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) {
             if !self.run_rustfix {
                 self.run_rustfix = config.parse_run_rustfix(ln);
             }
+
+            if !self.rustfix_only_machine_applicable {
+                self.rustfix_only_machine_applicable =
+                    config.parse_rustfix_only_machine_applicable(ln);
+            }
         });
 
         if self.failure_status == -1 {
@@ -663,6 +670,10 @@ fn parse_run_rustfix(&self, line: &str) -> bool {
         self.parse_name_directive(line, "run-rustfix")
     }
 
+    fn parse_rustfix_only_machine_applicable(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "rustfix-only-machine-applicable")
+    }
+
     fn parse_edition(&self, line: &str) -> Option<String> {
         self.parse_name_value_directive(line, "edition")
     }
index ce7828144cd0ca5279a5348881faea49a0d8ccbe..c8f3956415d533dfd384e3e2136e1ab083a3f1e3 100644 (file)
@@ -2624,7 +2624,11 @@ fn run_ui_test(&self) {
             let suggestions = get_suggestions_from_json(
                 &proc_res.stderr,
                 &HashSet::new(),
-                Filter::Everything,
+                if self.props.rustfix_only_machine_applicable {
+                    Filter::MachineApplicableOnly
+                } else {
+                    Filter::Everything
+                },
             ).unwrap();
             let fixed_code = apply_suggestions(&unfixed_code, &suggestions).expect(&format!(
                 "failed to apply suggestions for {:?} with rustfix",
@@ -2686,7 +2690,7 @@ fn run_ui_test(&self) {
             if !res.status.success() {
                 self.fatal_proc_rec("failed to compile fixed code", &res);
             }
-            if !res.stderr.is_empty() {
+            if !res.stderr.is_empty() && !self.props.rustfix_only_machine_applicable {
                 self.fatal_proc_rec("fixed code is still producing diagnostics", &res);
             }
         }
index 91e7399f1f492288cc5184d006fc850074b6abc6..2a716970ca7b9a03edead9992cc41fa2dc203e0b 100644 (file)
@@ -25,6 +25,7 @@
     ("freebsd", "freebsd"),
     ("fuchsia", "fuchsia"),
     ("haiku", "haiku"),
+    ("hermit", "hermit"),
     ("ios", "ios"),
     ("l4re", "l4re"),
     ("linux", "linux"),
index e72f90554d3c504bcc144b01f6cda4387912ac36..40917cc5db0d5f6eba8086615706c1774d4d9793 100644 (file)
 use std::io::{Read, Write};
 use std::path::Path;
 use std::path::PathBuf;
+use std::cell::RefCell;
 
 use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};
 
-use rustdoc::html::markdown::{Markdown, PLAYGROUND};
+use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, PLAYGROUND};
 use rustc_serialize::json;
 
 enum OutputFormat {
@@ -36,7 +37,7 @@ enum OutputFormat {
 impl OutputFormat {
     fn from(format: &str) -> OutputFormat {
         match &*format.to_lowercase() {
-            "html"     => OutputFormat::HTML(HTMLFormatter),
+            "html"     => OutputFormat::HTML(HTMLFormatter(RefCell::new(IdMap::new()))),
             "markdown" => OutputFormat::Markdown(MarkdownFormatter),
             s          => OutputFormat::Unknown(s.to_owned()),
         }
@@ -51,7 +52,7 @@ fn error_code_block(&self, output: &mut dyn Write, info: &ErrorMetadata,
     fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>>;
 }
 
-struct HTMLFormatter;
+struct HTMLFormatter(RefCell<IdMap>);
 struct MarkdownFormatter;
 
 impl Formatter for HTMLFormatter {
@@ -100,7 +101,11 @@ fn error_code_block(&self, output: &mut dyn Write, info: &ErrorMetadata,
 
         // Description rendered as markdown.
         match info.description {
-            Some(ref desc) => write!(output, "{}", Markdown(desc, &[]))?,
+            Some(ref desc) => {
+                let mut id_map = self.0.borrow_mut();
+                write!(output, "{}",
+                    Markdown(desc, &[], RefCell::new(&mut id_map), ErrorCodes::Yes))?
+            },
             None => write!(output, "<p>No description.</p>\n")?,
         }
 
index 8214ccf861d538671b0a1436dbf4538dc4a64d09..f76ea3ca16ed22dde8ef929db74a4b4df6f2f899 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 8214ccf861d538671b0a1436dbf4538dc4a64d09
+Subproject commit f76ea3ca16ed22dde8ef929db74a4b4df6f2f899
index 4c7cc91d5518bd29d3d59599cfb7a2e7e848d7b7..6d72813199d24838636389c7025ce95c427692f7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4c7cc91d5518bd29d3d59599cfb7a2e7e848d7b7
+Subproject commit 6d72813199d24838636389c7025ce95c427692f7
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
new file mode 100644 (file)
index 0000000..8c947bb
--- /dev/null
@@ -0,0 +1,44 @@
+[package]
+name = "rustc-workspace-hack"
+version = "1.0.0"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+license = 'MIT/Apache-2.0'
+description = """
+Hack for the compiler's own build system
+"""
+
+[lib]
+path = "lib.rs"
+
+# For documentation about what this is and why in the world these dependencies
+# are appearing, see `README.md`.
+
+[build-dependencies]
+# Currently Cargo/RLS depend on `failure` which depends on `synstructure` which
+# enables this feature. Clippy, however, does not depend on anything that
+# enables this feature. Enable it unconditionally.
+syn = { version = "0.14", features = ['extra-traits'] }
+
+[target.'cfg(windows)'.dependencies.winapi]
+version = "0.3"
+features = [
+  "profileapi",
+  "memoryapi",
+  "minschannel",
+  "securitybaseapi",
+  "jobapi2",
+  "schannel",
+  "sysinfoapi",
+  "jobapi",
+  "synchapi",
+  "wincrypt",
+  "winbase",
+  "minwinbase",
+  "ntsecapi",
+  "basetsd",
+  "ntstatus",
+  "psapi",
+  "timezoneapi",
+  "lmcons",
+  "wincon",
+]
diff --git a/src/tools/rustc-workspace-hack/README.md b/src/tools/rustc-workspace-hack/README.md
new file mode 100644 (file)
index 0000000..4a5286f
--- /dev/null
@@ -0,0 +1,25 @@
+# `rustc-workspace-hack`
+
+This crate is a bit of a hack to make workspaces in rustc work a bit better.
+The rationale for this existence is a bit subtle, but the general idea is that
+we want commands like `./x.py build src/tools/{rls,clippy,cargo}` to share as
+many dependencies as possible.
+
+Each invocation is a different invocation of Cargo, however. Each time Cargo
+runs a build it will re-resolve the dependency graph, notably selecting
+different features sometimes for each build.
+
+For example, let's say there's a very deep dependency like `num-traits` in each
+of these builds. For Cargo the `num-traits`'s `default` feature is turned off.
+In RLS, however, the `default` feature is turned. This means that building Cargo
+and then the RLS will actually build Cargo twice (as a transitive dependency
+changed). This is bad!
+
+The goal of this crate is to solve this problem and ensure that the resolved
+dependency graph for all of these tools is the same in the various subsets of
+each tool, notably enabling the same features of transitive dependencies.
+
+All tools vendored here depend on the `rustc-workspace-hack` crate on crates.io.
+When on crates.io this crate is an empty crate that is just a noop. We override
+it, however, in this workspace to this crate here, which means we can control
+crates in the dependency graph for each of these tools.
diff --git a/src/tools/rustc-workspace-hack/lib.rs b/src/tools/rustc-workspace-hack/lib.rs
new file mode 100644 (file)
index 0000000..ab26297
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// intentionally left blank
index 69ad879d52606ac03440744efa5b4d8ca8cc7566..da17b689595ddc863b02eb1ba6831c87cefc1e21 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 69ad879d52606ac03440744efa5b4d8ca8cc7566
+Subproject commit da17b689595ddc863b02eb1ba6831c87cefc1e21